B-1_14-DEV merge back to main

This commit is contained in:
clay_shooter
2008-02-02 01:38:25 +00:00
parent cd58b57a99
commit df0ba33797
97 changed files with 12208 additions and 8816 deletions

View File

@@ -4,6 +4,7 @@ jacobdll.jar
*.zip *.zip
RELEASE.txt RELEASE.txt
.project .project
.cproject
.classpath .classpath
compilation_tools.properties compilation_tools.properties
version.properties version.properties
@@ -13,3 +14,4 @@ release
foo.foo foo.foo
foo.ser foo.ser
JacobVersion.properties

180
build.xml
View File

@@ -16,15 +16,15 @@
The file for MS Visual C++ 8.0 building 32 and 64 bit The file for MS Visual C++ 8.0 building 32 and 64 bit
(releases up to 1.11 only supported 32 builds) looks something like: (releases up to 1.11 only supported 32 builds) looks something like:
JDK=d:\\j2sdk1.4.2_14 JDK=d:\\jdk1.5.0_11
MSDEV_DIR=d:\\apps\\Microsoft Visual Studio 8\\VC MSDEV_DIR=d:\\apps\\Microsoft Visual Studio 8\\VC
MSDEV_IDE_DIR=d:\\apps\\Microsoft Visual Studio 8\\Common7\\IDE MSDEV_IDE_DIR=d:\\apps\\Microsoft Visual Studio 8\\Common7\\IDE
version=1.13 version=1.14-M1
DO NOT check compilation_tools.properties into source control as the DO NOT check compilation_tools.properties into source control as the
values are specific to YOUR environment. values are specific to YOUR environment.
The version.properties file is now completely autogenerated The JacobVersion.properties file is now completely autogenerated
====================================================================== --> ====================================================================== -->
<project name="jacob" default="default" basedir="."> <project name="jacob" default="default" basedir=".">
@@ -49,15 +49,17 @@
<property name="application.title" value="JACOB : Java COM Bridge" /> <property name="application.title" value="JACOB : Java COM Bridge" />
<property name="application.vendor" value="http://jacob-project.sourceforge.net" /> <property name="application.vendor" value="http://jacob-project.sourceforge.net" />
<property name="src.java.jacob.mainpackage" value="com.jacob" /> <property name="src.java.mainpackage" value="com.jacob" />
<property name="java.class.main" value="com.jacob.com.Jacob" /> <property name="java.class.main" value="com.jacob.com.Jacob" />
<property name="generated.filename.dll" value="jacob.dll" /> <property name="generated.filename.dll.x86" value="jacob-${version}-x86.dll" />
<property name="generated.filename.dll.x64" value="jacob-${version}-x64.dll" />
<property name="generated.filename.jar" value="jacob.jar" /> <property name="generated.filename.jar" value="jacob.jar" />
<property name="generated.filename.zip" value="jacob_${version}" /> <property name="generated.filename.zip" value="jacob-${version}" />
<property name="generated.filename.version" value="JacobVersion.properties" />
<property name="junit.jar" value="${basedir}\lib\junit3.8.1\junit.jar" /> <property name="junit.jar" value="${basedir}\lib\junit3.8.1\junit.jar" />
<property name="src.java.jacob" value="${basedir}/src" /> <property name="src.java.mainroot" value="${basedir}/src" />
<property name="src.java.samples" value="${basedir}/samples" /> <property name="src.java.samples" value="${basedir}/samples" />
<property name="src.java.unittest" value="${basedir}/unittest" /> <property name="src.java.unittest" value="${basedir}/unittest" />
<property name="src.cpp" value="${basedir}/jni" /> <property name="src.cpp" value="${basedir}/jni" />
@@ -66,13 +68,14 @@
<property name="release.dir.x86" value="${release.dir}\x86" /> <property name="release.dir.x86" value="${release.dir}\x86" />
<property name="release.dir.x86.cpp" value="${release.dir.x86}\jni" /> <property name="release.dir.x86.cpp" value="${release.dir.x86}\jni" />
<property name="release.file.x86.dll" value="${release.dir.x86}\${generated.filename.dll}" /> <property name="release.file.x86.dll" value="${release.dir.x86}\${generated.filename.dll.x86}" />
<property name="release.dir.AMD64" value="${release.dir}\AMD64" /> <property name="release.dir.x64" value="${release.dir}\x64" />
<property name="release.dir.AMD64.cpp" value="${release.dir.AMD64}\jni" /> <property name="release.dir.x64.cpp" value="${release.dir.x64}\jni" />
<property name="release.file.AMD64.dll" value="${release.dir.AMD64}\${generated.filename.dll}" /> <property name="release.file.x64.dll" value="${release.dir.x64}\${generated.filename.dll.x64}" />
<property name="release.dir.java" value="${release.dir}\java" /> <property name="release.dir.java" value="${release.dir}\java" />
<property name="release.dir.java.meta.inf" value="${release.dir.java}\META-INF" />
<property name="release.file.jar" value="${release.dir.java}\${generated.filename.jar}" /> <property name="release.file.jar" value="${release.dir.java}\${generated.filename.jar}" />
<property name="compiler.x86" value="${MSDEV_DIR}\bin\cl.exe" /> <property name="compiler.x86" value="${MSDEV_DIR}\bin\cl.exe" />
@@ -87,13 +90,13 @@
<!-- You have to love the beautiful asymetry of the MS world --> <!-- You have to love the beautiful asymetry of the MS world -->
<!-- The platform SDK comes with 64 bit tools but not 32 bit tools --> <!-- The platform SDK comes with 64 bit tools but not 32 bit tools -->
<property name="compiler.AMD64" value="${MSDEV_DIR}\bin\x86_amd64\cl.exe" /> <property name="compiler.x64" value="${MSDEV_DIR}\bin\x86_amd64\cl.exe" />
<property name="linker.AMD64" value="${MSDEV_DIR}\bin\x86_amd64\link.exe" /> <property name="linker.x64" value="${MSDEV_DIR}\bin\x86_amd64\link.exe" />
<property name="manifesttool.AMD64" value="${MSDEV_DIR}\bin\x86_amd64\mt.exe" /> <property name="manifesttool.x64" value="${MSDEV_DIR}\bin\x86_amd64\mt.exe" />
<property name="include.AMD64" value="${MSDEV_DIR}\include" /> <property name="include.x64" value="${MSDEV_DIR}\include" />
<property name="library.AMD64" value="${MSDEV_DIR}\lib\AMD64" /> <property name="library.x64" value="${MSDEV_DIR}\lib\amd64" />
<property name="library.AMD64.platformSDK" value="${MSDEV_DIR}\PlatformSDK\lib\AMD64" /> <property name="library.x64.platformSDK" value="${MSDEV_DIR}\PlatformSDK\lib\amd64" />
<property name="library.AMD64.atl" value="${MSDEV_DIR}\atlmfc\lib\AMD64" /> <property name="library.x64.atl" value="${MSDEV_DIR}\atlmfc\lib\amd64" />
<!-- ====================================================================== <!-- ======================================================================
@@ -101,73 +104,75 @@
already there) already there)
================================================================== --> ================================================================== -->
<mkdir dir="${release.dir.java}"/> <mkdir dir="${release.dir.java}"/>
<mkdir dir="${release.dir.java.meta.inf}"/>
<mkdir dir="${release.dir.x86.cpp}"/> <mkdir dir="${release.dir.x86.cpp}"/>
<mkdir dir="${release.dir.AMD64.cpp}"/> <mkdir dir="${release.dir.x64.cpp}"/>
<mkdir dir="${release.dir}"/> <mkdir dir="${release.dir}"/>
<!-- ====================================================================== <!-- ======================================================================
Writes out a version file to be included in the jar Writes out a version file to be included in the jar
================================================================== --> ================================================================== -->
<property name="version" value="version not set in compilation_tools properties file"/> <property name="version" value="version not set in compilation_tools properties file"/>
<propertyfile file="version.properties"> <propertyfile file="${generated.filename.version}">
<entry key="version" type="string" value="${version}" /> <entry key="version" type="string" value="${version}" />
<entry key="build.iteration" type="int" operation="+" value="1" pattern="00" /> <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" /> <entry key="build.date" type="date" value="now" operation="=" pattern="dd-MMMM-yyyy HH:mm:ss" />
</propertyfile> </propertyfile>
<property file="version.properties" /> <property file="${generated.filename.version}" />
<!-- ====================================================================== <!-- ======================================================================
32 bit x86 can only be built on 32 bit because of a JDK library issue. 32 bit X86 can only be built on 32 bit because of a JDK library issue.
arch=x86 true if on 32 bit, unset in all other cases. arch=X86 true if on 32 bit, unset in all other cases.
This module used to rely on that. Now it just checks to see if we have This module used to rely on that. Now it just checks to see if we have
the right compilers. the right compilers.
================================================================== --> ================================================================== -->
<available file="${compiler.x86}" property="canBuildX86"/> <available file="${compiler.x86}" property="canBuild.x86"/>
<echo message="canBuildX86=${canBuildX86}" /> <echo message="canBuild.x86=${canBuild.x86}" />
<available file="${compiler.AMD64}" property="canBuildAMD64"/> <available file="${compiler.x64}" property="canBuild.x64"/>
<echo message="canBuildAMD64=${canBuildAMD64}" /> <echo message="canBuild.x64=${canBuild.x64}" />
<!-- ====================================================================== <!-- ======================================================================
Compare the date/time of the DLL against that of the cpp source. Compare the date/time of the DLL against that of the cpp source.
Up to date is only true if dll exists and is later than source Up to date is only true if dll exists and is later than source
================================================================== --> ================================================================== -->
<uptodate property="dllUpToDateX86" targetfile="${release.file.x86.dll}"> <uptodate property="dllUpToDate.x86" targetfile="${release.file.x86.dll}">
<srcfiles dir="${src.cpp}" includes="*.cpp" /> <srcfiles dir="${src.cpp}" includes="*.cpp" />
<srcfiles dir="${src.cpp}" includes="*.h" /> <srcfiles dir="${src.cpp}" includes="*.h" />
<!-- Check the build file itself as well --> <!-- Check the build file itself as well -->
<srcfiles dir="${basedir}" includes="build.xml" /> <srcfiles dir="${basedir}" includes="build.xml" />
</uptodate> </uptodate>
<echo message="dllUpToDateX86= ${dllUpToDateX86} (${release.file.x86.dll})" /> <echo message="dllUpToDate.x86= ${dllUpToDate.x86} (${release.file.x86.dll})" />
<uptodate property="dllUpToDateAMD64" targetfile="${release.file.AMD64.dll}">
<uptodate property="dllUpToDate.x64" targetfile="${release.file.x64.dll}">
<srcfiles dir="${src.cpp}" includes="*.cpp" /> <srcfiles dir="${src.cpp}" includes="*.cpp" />
<srcfiles dir="${src.cpp}" includes="*.h" /> <srcfiles dir="${src.cpp}" includes="*.h" />
<!-- Check the build file itself as well --> <!-- Check the build file itself as well -->
<srcfiles dir="${basedir}" includes="build.xml" /> <srcfiles dir="${basedir}" includes="build.xml" />
</uptodate> </uptodate>
<echo message="dllUpToDateAMD64= ${dllUpToDateAMD64} (${release.file.AMD64.dll})" /> <echo message="dllUpToDate.x64= ${dllUpToDate.x64} (${release.file.x64.dll})" />
<!-- ====================================================================== <!-- ======================================================================
We should build if we can build and the dll is not up to date We should build if we can build and the dll is not up to date
================================================================== --> ================================================================== -->
<condition property="shouldBuildX86"> <condition property="shouldBuild.x86">
<and> <and>
<isset property="canBuildX86"/> <isset property="canBuild.x86"/>
<not> <not>
<isset property="dllUpToDateX86"/> <isset property="dllUpToDate.x86"/>
</not> </not>
</and> </and>
</condition> </condition>
<echo message="shouldBuildX86= ${shouldBuildX86}" /> <echo message="shouldBuild.x86= ${shouldBuild.x86}" />
<condition property="shouldBuildAMD64"> <condition property="shouldBuild.x64">
<and> <and>
<isset property="canBuildAMD64"/> <isset property="canBuild.x64"/>
<not> <not>
<isset property="dllUpToDateAMD64"/> <isset property="dllUpToDate.x64"/>
</not> </not>
</and> </and>
</condition> </condition>
<echo message="shouldBuildAMD64= ${shouldBuildAMD64}" /> <echo message="shouldBuild.x64= ${shouldBuild.x64}" />
<!--=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=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=v=v=v=v
@@ -178,7 +183,7 @@
target: default target: default
================================= --> ================================= -->
<target name="default" <target name="default"
depends="javaJarBin,makeDllX86,makeDllAMD64"> depends="javaJarBin,makeDll.x86,makeDll.x64">
<echo message="${application.title} ${version} build ${build.iteration} : finished on ${build.date}" /> <echo message="${application.title} ${version} build ${build.iteration} : finished on ${build.date}" />
</target> </target>
@@ -189,7 +194,7 @@
<delete> <delete>
<fileset dir="${release.dir.java}"/> <fileset dir="${release.dir.java}"/>
<fileset dir="${release.dir.x86.cpp}"/> <fileset dir="${release.dir.x86.cpp}"/>
<fileset dir="${release.dir.AMD64.cpp}"/> <fileset dir="${release.dir.x64.cpp}"/>
<fileset dir="${release.dir}"/> <fileset dir="${release.dir}"/>
</delete> </delete>
</target> </target>
@@ -199,38 +204,38 @@
================================================================== --> ================================================================== -->
<target name="javaJarCheck"> <target name="javaJarCheck">
<uptodate property="jarUpToDate" targetfile="${release.file.jar}"> <uptodate property="jarUpToDate" targetfile="${release.file.jar}">
<srcfiles dir="${src.java.jacob}" includes="com/**/*.java" /> <srcfiles dir="${src.java.mainroot}" includes="com/**/*.java" />
<!-- Check the build file itself as well --> <!-- Check the build file itself as well -->
<srcfiles dir="${basedir}" includes="build.xml" /> <srcfiles dir="${basedir}" includes="build.xml" />
</uptodate> </uptodate>
<echo message="javaJarCheck says jarUpToDate= ${jarUpToDate}" /> <echo message="javaJarCheck says jarUpToDate= ${jarUpToDate}" />
</target> </target>
<!-- ====================================================================== <!-- ======================================================================
Compile the java files and copy version.properties to be jar'd up Compile the java files and copy JacobVersion.properties to be jar'd up
Relies on ant recognizing when a file needs to be compiled Relies on ant recognizing when a file needs to be compiled
Unit tests compiled seperately because of junit dependency Unit tests compiled seperately because of junit dependency
================================================================== --> ================================================================== -->
<target name="javaCompile" > <target name="javaCompile" >
<echo>Building Jacob classes in ${release.dir.java}</echo> <echo>Building Jacob classes in ${release.dir.java}</echo>
<javac srcdir="${src.java.jacob}" <javac srcdir="${src.java.mainroot}"
destdir="${release.dir.java}" destdir="${release.dir.java}"
listfiles="true" debug="on" source="1.4" /> listfiles="true" debug="on" source="1.5" />
<echo>Building sample classes in ${release.dir.java}</echo> <echo>Building sample classes in ${release.dir.java}</echo>
<javac srcdir="${src.java.samples}" <javac srcdir="${src.java.samples}"
destdir="${release.dir.java}" destdir="${release.dir.java}"
classpath="${release.dir.java}" classpath="${release.dir.java}"
listfiles="true" debug="on" source="1.4" /> listfiles="true" debug="on" source="1.5" />
<echo>Building Jacob test classes in ${release.dir.java} using junit jar ${junit.jar}</echo> <echo>Building Jacob test classes in ${release.dir.java} using junit jar ${junit.jar}</echo>
<javac srcdir="${src.java.unittest}" <javac srcdir="${src.java.unittest}"
destdir="${release.dir.java}" destdir="${release.dir.java}"
classpath="${release.dir.java}:${junit.jar}" classpath="${release.dir.java}:${junit.jar}"
listfiles="true" debug="on" source="1.4" /> listfiles="true" debug="on" source="1.5" />
<copy file="version.properties" todir="${release.dir.java}"/> <copy file="${generated.filename.version}" todir="${release.dir.java.meta.inf}"/>
</target> </target>
<!-- ====================================================================== <!-- ======================================================================
Package the classes into a JAR. Package the classes into a JAR.
Put version.propertes into the jar file so version retrieval method can find it Put JacobVersion.properties into the jar file so version retrieval method can find it
================================================================== --> ================================================================== -->
<target name="javaJarBin" <target name="javaJarBin"
depends="javaCompile,javaJarCheck" depends="javaCompile,javaJarCheck"
@@ -238,6 +243,7 @@
<echo>Removing old jars</echo> <echo>Removing old jars</echo>
<delete file="${release.file.jar}" /> <delete file="${release.file.jar}" />
<echo>Packaging java classes...</echo> <echo>Packaging java classes...</echo>
<echo>Version File is ${release.dir.java.meta.inf}/${generated.filename.version}</echo>
<jar destfile="${release.file.jar}" basedir="${release.dir.java}" update="false"> <jar destfile="${release.file.jar}" basedir="${release.dir.java}" update="false">
<exclude name="**/CVS" /> <exclude name="**/CVS" />
<!-- exclude all unit tests (ending in Test) <!-- exclude all unit tests (ending in Test)
@@ -246,11 +252,11 @@
<exclude name="com/jacob/samples/**"/> <exclude name="com/jacob/samples/**"/>
<exclude name="com/jacob/test/**"/> <exclude name="com/jacob/test/**"/>
<include name="com/**/*.class" /> <include name="com/**/*.class" />
<include name="version.properties" /> <include name="META-INF/${generated.filename.version}" />
<manifest> <manifest>
<attribute name="Built-By" value="${user.name}" /> <attribute name="Built-By" value="${user.name}" />
<attribute name="Main-Class" value="${java.class.main}"/> <attribute name="Main-Class" value="${java.class.main}"/>
<section name="${src.java.jacob.mainpackage}"> <section name="${src.java.mainpackage}">
<attribute name="Specification-Title" value="${application.title}" /> <attribute name="Specification-Title" value="${application.title}" />
<attribute name="Specification-Vendor" value="${application.vendor}" /> <attribute name="Specification-Vendor" value="${application.vendor}" />
<attribute name="Implementation-Title" value="${application.title} Java libraries" /> <attribute name="Implementation-Title" value="${application.title} Java libraries" />
@@ -262,10 +268,10 @@
<!-- ====================================================================== <!-- ======================================================================
Compile the c source files. Compile the c source files.
================================================================== --> ================================================================== -->
<target name="compileX86" if="shouldBuildX86"> <target name="compile.x86" if="shouldBuild.x86">
<echo>Clean up the (x86) target folders and file, for safety</echo> <echo>Clean up the (X86) target folders and file, for safety</echo>
<delete file="${release.dir.x86.cpp}/**/*.*" /> <delete file="${release.dir.x86.cpp}/**/*.*" />
<echo>Compiling (x86) C++ classes with JDK JNI library ${JDK}</echo> <echo>Compiling (X86) C++ classes with JDK JNI library ${JDK}</echo>
<exec executable="${compiler.x86}" dir="${release.dir.x86.cpp}" failonerror="true"> <exec executable="${compiler.x86}" dir="${release.dir.x86.cpp}" failonerror="true">
<env key="Path" value="${MSDEV_IDE_DIR}"/> <env key="Path" value="${MSDEV_IDE_DIR}"/>
<env key="include" value="${JDK}\include;${JDK}\include\win32;${include.x86.platformSDK};${include.x86};${include.x86.atl}"/> <env key="include" value="${JDK}\include;${JDK}\include\win32;${include.x86.platformSDK};${include.x86};${include.x86.atl}"/>
@@ -294,11 +300,11 @@
</exec> </exec>
</target> </target>
<target name="compileAMD64" if="shouldBuildAMD64"> <target name="compile.x64" if="shouldBuild.x64">
<echo>Clean up the (AMD64) target folders and file, for safety</echo> <echo>Clean up the (x64) target folders and file, for safety</echo>
<delete file="${release.dir.AMD64.cpp}/**/*.*" /> <delete file="${release.dir.x64.cpp}/**/*.*" />
<echo>Compiling C++ (AMD64) classes with JDK JNI library ${JDK}</echo> <echo>Compiling C++ (x64) classes with JDK JNI library ${JDK}</echo>
<exec executable="${compiler.AMD64}" dir="${release.dir.AMD64.cpp}" failonerror="true"> <exec executable="${compiler.x64}" dir="${release.dir.x64.cpp}" failonerror="true">
<env key="include" value="${JDK}\include;${JDK}\include\win32;${include.x86.platformSDK};${include.x86};${include.x86.atl}"/> <env key="include" value="${JDK}\include;${JDK}\include\win32;${include.x86.platformSDK};${include.x86};${include.x86.atl}"/>
<env key="Path" value="${MSDEV_IDE_DIR}"/> <env key="Path" value="${MSDEV_IDE_DIR}"/>
<arg value="/nologo"/> <arg value="/nologo"/>
@@ -334,7 +340,7 @@
32 bit target Yes No 32 bit target Yes No
64 bit target Yes Yes 64 bit target Yes Yes
================================================================== --> ================================================================== -->
<target name="makeDllX86" depends="compileX86" if="shouldBuildX86"> <target name="makeDll.x86" depends="compile.x86" if="shouldBuild.x86">
<echo>Clean up the target folders and file, for safety</echo> <echo>Clean up the target folders and file, for safety</echo>
<echo>Using ${library.x86}</echo> <echo>Using ${library.x86}</echo>
<delete file="${release.file.x86.dll}" /> <delete file="${release.file.x86.dll}" />
@@ -361,40 +367,40 @@
</exec> </exec>
</target> </target>
<target name="makeDllAMD64" depends="compileAMD64" if="shouldBuildAMD64"> <target name="makeDll.x64" depends="compile.x64" if="shouldBuild.x64">
<echo>Clean up the target folders and file, for safety</echo> <echo>Clean up the target folders and file, for safety</echo>
<delete file="${release.file.AMD64.dll}" /> <delete file="${release.file.x64.dll}" />
<echo>Creating {$release.file.AMD64.dll}</echo> <echo>Creating {$release.file.x64.dll}</echo>
<exec executable="${linker.AMD64}" dir="${release.dir.AMD64.cpp}" failonerror="true"> <exec executable="${linker.x64}" dir="${release.dir.x64.cpp}" failonerror="true">
<env key="Path" value="${MSDEV_IDE_DIR}"/> <env key="Path" value="${MSDEV_IDE_DIR}"/>
<arg value="/nologo" /> <arg value="/nologo" />
<arg value="/MANIFEST" /> <arg value="/MANIFEST" />
<arg value="/MANIFESTFILE:${release.dir.AMD64.cpp}/jacob.dll.manifest" /> <arg value="/MANIFESTFILE:${release.dir.x64.cpp}/jacob.dll.manifest" />
<arg value="/dll" /> <arg value="/dll" />
<arg value="/version:${version}" /> <arg value="/version:${version}" />
<arg value="/out:${release.file.AMD64.dll}" /> <arg value="/out:${release.file.x64.dll}" />
<arg value="/libpath:${library.AMD64}" /> <arg value="/libpath:${library.x64}" />
<arg value="/libpath:${library.AMD64.platformSDK}" /> <arg value="/libpath:${library.x64.platformSDK}" />
<arg value="/libpath:${library.AMD64.atl}" /> <arg value="/libpath:${library.x64.atl}" />
<arg value="${JDK}\lib\jvm.lib" /> <arg value="${JDK}\lib\jvm.lib" />
<arg value="${release.dir.AMD64.cpp}/*.obj" /> <arg value="${release.dir.x64.cpp}/*.obj" />
</exec> </exec>
<exec executable="${manifestool.x86}" dir="${release.dir.AMD64.cpp}" failonerror="true"> <exec executable="${manifestool.x86}" dir="${release.dir.x64.cpp}" failonerror="true">
<env key="Path" value="${MSDEV_IDE_DIR}"/> <env key="Path" value="${MSDEV_IDE_DIR}"/>
<arg value="-outputresource:${release.file.AMD64.dll};2"/> <arg value="-outputresource:${release.file.x64.dll};2"/>
<arg value="-manifest"/> <arg value="-manifest"/>
<arg value="${release.dir.AMD64.cpp}\jacob.dll.manifest" /> <arg value="${release.dir.x64.cpp}\jacob.dll.manifest" />
</exec> </exec>
</target> </target>
<!-- ====================================================================== <!-- ======================================================================
Use this target to create javadoc from ${src.java.jacob.mainpackage}/* Use this target to create javadoc from ${src.java.mainpackage}/*
================================================================== --> ================================================================== -->
<target name="generateJavaDoc"> <target name="generateJavaDoc">
<defaultexcludes add="**/*Test*"/> <defaultexcludes add="**/*Test*"/>
<javadoc <javadoc
packagenames="${src.java.jacob.mainpackage}/**" packagenames="${src.java.mainpackage}/**"
sourcepath="${src.java.jacob}" sourcepath="${src.java.mainroot}"
destdir="${release.dir.java}/docs/api" destdir="${release.dir.java}/docs/api"
author="true" author="true"
version="true" version="true"
@@ -403,11 +409,11 @@
<doctitle><![CDATA[<h1>${application.title}</h1>]]></doctitle> <doctitle><![CDATA[<h1>${application.title}</h1>]]></doctitle>
<bottom><![CDATA[<i>${application.vendor}</i>]]></bottom> <bottom><![CDATA[<i>${application.vendor}</i>]]></bottom>
<group title="Core COM Communication" packages="${src.java.jacob.mainpackage}.com/**"/> <group title="Core COM Communication" packages="${src.java.mainpackage}.com/**"/>
<group title="Higher Level Active X" packages="${src.java.jacob.mainpackage}.activeX/**"/> <group title="Higher Level Active X" packages="${src.java.mainpackage}.activeX/**"/>
<group title="API Stub Generator" packages="${src.java.jacob.mainpackage}.jacobgen/**"/> <group title="API Stub Generator" packages="${src.java.mainpackage}.jacobgen/**"/>
<link offline="true" href="http://java.sun.com/j2se/1.4.2/docs/api/" packagelistLoc="C:\tmp"/> <link offline="true" href="http://java.sun.com/j2se/1.5.0/docs/api/" packagelistLoc="C:\tmp"/>
<link href="http://java.sun.com/j2se/1.4.2/docs/api/"/> <link href="http://java.sun.com/j2se/1.5.0/docs/api/"/>
</javadoc> </javadoc>
<defaultexcludes default="true"/> <defaultexcludes default="true"/>
</target> </target>
@@ -416,7 +422,7 @@
Use this target to package all the files for a release Use this target to package all the files for a release
================================================================== --> ================================================================== -->
<target name="PackageRelease" <target name="PackageRelease"
depends="makeDllX86,makeDllAMD64,javaJarBin,generateJavaDoc"> depends="makeDll.x86,makeDll.x64,javaJarBin,generateJavaDoc">
<echo>Packaging release... ${release.file.jar}</echo> <echo>Packaging release... ${release.file.jar}</echo>
<zip <zip
@@ -424,10 +430,10 @@
<exclude name="**/CVS" /> <exclude name="**/CVS" />
<exclude name="**/*.obj" /> <exclude name="**/*.obj" />
<exclude name="**/*.class" /> <exclude name="**/*.class" />
<zipfileset dir="${basedir}" prefix="${generated.filename.zip}" includes="LICENSE.* version.properties README.txt" /> <zipfileset dir="${basedir}" prefix="${generated.filename.zip}" includes="LICENSE.* ${generated.filename.version} README.txt" />
<zipfileset dir="${basedir}" prefix="${generated.filename.zip}" includes="docs/**" /> <zipfileset dir="${basedir}" prefix="${generated.filename.zip}" includes="docs/**" />
<zipfileset dir="${release.dir.x86}" prefix="${generated.filename.zip}/x86" includes="${generated.filename.dll}" /> <zipfileset dir="${release.dir.x86}" prefix="${generated.filename.zip}" includes="${generated.filename.dll.x86}" />
<zipfileset dir="${release.dir.AMD64}" prefix="${generated.filename.zip}/AMD64" includes="${generated.filename.dll}" /> <zipfileset dir="${release.dir.x64}" prefix="${generated.filename.zip}" includes="${generated.filename.dll.x64}" />
<zipfileset dir="${release.dir.java}" prefix="${generated.filename.zip}" includes="${generated.filename.jar}" /> <zipfileset dir="${release.dir.java}" prefix="${generated.filename.zip}" includes="${generated.filename.jar}" />
<zipfileset dir="${release.dir.java}" prefix="${generated.filename.zip}" includes="docs/**"/> <zipfileset dir="${release.dir.java}" prefix="${generated.filename.zip}" includes="docs/**"/>
</zip> </zip>
@@ -447,14 +453,14 @@
<zipfileset dir="${basedir}" prefix="${generated.filename.zip}" includes="vstudio/jacob.vcproj" /> <zipfileset dir="${basedir}" prefix="${generated.filename.zip}" includes="vstudio/jacob.vcproj" />
<zipfileset dir="${basedir}" prefix="${generated.filename.zip}" includes="lib/**" /> <zipfileset dir="${basedir}" prefix="${generated.filename.zip}" includes="lib/**" />
<zipfileset dir="${basedir}" prefix="${generated.filename.zip}" includes="build.xml, README.txt" /> <zipfileset dir="${basedir}" prefix="${generated.filename.zip}" includes="build.xml, README.txt" />
<zipfileset dir="${basedir}" prefix="${generated.filename.zip}" includes="LICENSE.* version.properties" /> <zipfileset dir="${basedir}" prefix="${generated.filename.zip}" includes="LICENSE.* ${generated.filename.version}" />
</zip> </zip>
</target> </target>
<!-- ====================================================================== <!-- ======================================================================
JUnit testing JUnit testing
This should probably be dependent on dll also This should probably be dependent on dll also
This assumes we are always testing on x86 This assumes we are always testing on X86
This assumes that ant-junit is available This assumes that ant-junit is available
================================================================== --> ================================================================== -->
<target name='test' depends='javaCompile' > <target name='test' depends='javaCompile' >

View File

@@ -34,20 +34,20 @@ been removed.
<p> <p>
<H1>Development Environment</h1> <H1>Development Environment</h1>
The simplest build environment includes MS Visual C++ 8.0 (Studio 2005), The simplest build environment includes MS Visual C++ 8.0 (Studio 2005),
Eclipse 3.3 with the C/C++ module and JDK 1.4. Eclipse 3.3 with the C/C++ module and JDK 1.5.
In that situation, you would just create the <i>compilation_tools.properties</i> In that situation, you would just create the <i>compilation_tools.properties</i>
using the example build.xml as a template. using the example build.xml as a template.
<UL> <UL>
<li> Microsoft Visual C++ 8.0 and it's included library. (to D:\apps in my case) <li> Microsoft Visual C++ 8.0 and it's included library. (to D:\apps in my case)
<li> Eclipse 3.3 or later from www.eclipse.org as the Java IDE. <li> Eclipse 3.3 or later from www.eclipse.org as the Java IDE.
<li> Eclipse 3.3 or later with the C/C++ plugin can be used for C coding in place of VC++ IDE. <li> Eclipse 3.3 or later with the C/C++ plugin can be used for C coding in place of VC++ IDE.
<li> Java JDK 1.4 (1.12 was built using 1.4.2.13) Compilation using JDK 1.5 has not been tested <li> Java JDK 1.5 (1.14 was built using 1.5.0.11)
</ul> </ul>
<p> <p>
<p> <p>
<table> <table>
<TR><TD>Release</TD><TD>C Version</TD><TD>Java Version</TD><TD>ANT Version</TD><TD>Eclipse Version Used</TD><TD>generated DLLs</TD></TR> <TR><TD>Release</TD><TD>C Version</TD><TD>Java Version</TD><TD>ANT Version</TD><TD>Eclipse Version Used</TD><TD>generated DLLs</TD></TR>
<TR><TD>up to 1.6</TD><TD>VC 98 (6.0)</TD><TD>?</TD><td>Used MAKE</td><TD>?</TD><TD>32 bit</TD></TR> <TR><TD>up to 1.6</TD><TD>VC 98 (6.0)</TD><TD>?</TD><td>MAKE</td><TD>?</TD><TD>32 bit</TD></TR>
<TR><TD>1.7</TD><TD>VC 98 (6.0)</TD><TD>1.4</TD><td>1.?</td><TD>?</TD><TD>32 bit</TD></TR> <TR><TD>1.7</TD><TD>VC 98 (6.0)</TD><TD>1.4</TD><td>1.?</td><TD>?</TD><TD>32 bit</TD></TR>
<TR><TD>1.8</TD><TD>VC 98 (6.0)</TD><TD>1.4</TD><td>1.?</td><TD>?</TD><TD>32 bit</TD></TR> <TR><TD>1.8</TD><TD>VC 98 (6.0)</TD><TD>1.4</TD><td>1.?</td><TD>?</TD><TD>32 bit</TD></TR>
<TR><TD>1.9</TD><TD>VC 98 (6.0)</TD><TD>1.4</TD><td>1.?</td><TD>?</TD><TD>32 bit</TD></TR> <TR><TD>1.9</TD><TD>VC 98 (6.0)</TD><TD>1.4</TD><td>1.?</td><TD>?</TD><TD>32 bit</TD></TR>
@@ -55,6 +55,7 @@ using the example build.xml as a template.
<TR><TD>1.11</TD><TD>VC 98 (6.0) & 2003 64bit libs</TD><TD>1.4.?</TD><td>1.6.?</td><TD>3.2.1</TD><TD>32 and 64 bit</TD></TR> <TR><TD>1.11</TD><TD>VC 98 (6.0) & 2003 64bit libs</TD><TD>1.4.?</TD><td>1.6.?</td><TD>3.2.1</TD><TD>32 and 64 bit</TD></TR>
<TR><TD>1.12</TD><TD>VC 98 (6.0) & 2003 64bit libs</TD><TD>1.4.2</TD><td>1.6.5</td><TD>3.2.2</TD><TD>32 and 64 bit</TD></TR> <TR><TD>1.12</TD><TD>VC 98 (6.0) & 2003 64bit libs</TD><TD>1.4.2</TD><td>1.6.5</td><TD>3.2.2</TD><TD>32 and 64 bit</TD></TR>
<TR><TD>1.13</TD><TD>VC 2005</TD><TD>1.4.2</TD><TD>1.7.0</TD><TD>3.3</TD><TD>32 and 64 bit</TD></TR> <TR><TD>1.13</TD><TD>VC 2005</TD><TD>1.4.2</TD><TD>1.7.0</TD><TD>3.3</TD><TD>32 and 64 bit</TD></TR>
<TR><TD>1.14</TD><TD>VC 2005</TD><TD>1.5.0</TD><TD>1.7.0</TD><TD>3.3</TD><TD>32 and 64 bit</TD></TR>
</table> </table>
Microsoft Visual C++ 8.0 supports 64 bit builds. so no additional tools are required. Microsoft Visual C++ 8.0 supports 64 bit builds. so no additional tools are required.

View File

@@ -1,5 +1,113 @@
<HTML> <HTML>
<BODY> <BODY>
<!-- --------- -->
<h2>JACOB 1.14</h2>
<h3>What's New</h3>
<ul>
<li>
Binaries are now compiled with Java 5. JDK 1.4 support dropped.
</li>
<li>
Jacob now loads dlls based on platform (32 bit /64 bit) and version number.
</li>
</ul>
<h3>Tracked Changes</h3>
<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%" valign="top">1857439</td>
<td width="87%" valign="top">(M7) version.properties renamed to META-INF/JacobVersion.properties
to remove collision with WebSphere version.properties.</td>
</tr>
<tr>
<td width="13%" valign="top">1840487</td>
<td width="87%" valign="top">(M6) toJavaObject() converting to SafeArray
did shallow copy that left two objects pointing at the same windows memory.</td>
</tr>
<tr>
<td width="13%" valign="top">1829201</td>
<td width="87%" valign="top">(M5) DECIMAL rounding behavior externalized
and old Variant decimal API restored.</td>
</tr>
<tr>
<td width="13%" valign="top">1829201</td>
<td width="87%" valign="top">(M5) DECIMAL rounding behavior externalized
and old Variant decimal API restored.</td>
</tr>
<tr>
<td width="13%" valign="top">1829201</td>
<td width="87%" valign="top">(M4) Decimal type now throws IllegalArgumentException
when more than 12 bytes worth the digits exist in BigDecimal. Rounding
support added to reduce precision of BigDecimals when converting into VT_DECIMAL</td>
</tr>
<tr>
<td width="13%" valign="top">1815163</td>
<td width="87%" valign="top">(M2) Double and Decimal conversion to Int fails for negative values</td>
</tr>
<tr>
<td width="13%" valign="top">&nbsp;</td>
<td width="87%" valign="top">&nbsp;</td>
</tr>
<tr>
<td width="100%" colspan="2"><b>Patches</b></td>
</tr>
<tr>
<td width="13%" valign="top">&nbsp;</td>
<td width="87%" valign="top">&nbsp;</td>
</tr>
<tr>
<td width="100%" colspan="2"><b>Feature Requests</b></td>
</tr>
<tr>
<td width="13%" valign="top">1845039 </td>
<td width="87%" valign="top">(M7) Jacob DLL name can now be customized to
support bundling of Jacob in other products.</td>
</tr>
<td width="13%" valign="top">1845039 </td>
<td width="87%" valign="top">(M6) Jacob DLL names are now qualified by platform and
release. The JacobLibraryLoader now determines the correct 32bit or 64bit
dll based on the system architecture. Jacob.jar now also knows the version
of the dll it is looking for (by name) and loads the correct one. JWS clients
will have to modify their dll loaders. See: The JWS classloader sample </td>
</tr>
<tr>
<td width="13%" valign="top">1828371 </td>
<td width="87%" valign="top">(M4) Added VT_I8 support to SafeArray.</td>
</tr>
<tr>
<td width="13%" valign="top">1813458</td>
<td width="87%" valign="top">(M3) Expand type support. Changed currency support
to use new Currency class. Added VT_I8 64 bit support. VT_I8 support
requires Windows XP or later. VT_I8 not supported by windows in
Windows 2000 and earlier. Added more primitive constructors to Variant.</td>
</tr>
<tr>
<td width="13%" valign="top">1816863</td>
<td width="87%" valign="top">(M1) Migrate Jacob to JDK 5</td>
</tr>
<tr>
<td width="13%" valign="top">&nbsp;</td>
<td width="87%" valign="top">&nbsp;</td>
</tr>
<tr>
<td width="100%" colspan="2"><b>Known Issues</b></td>
</tr>
<tr>
<td width="13%" valign="top"></td>
<td width="87%" valign="top">This is now built with Java 5 compiler and
Java 5 syntax. This release is not compatible with JDK 1.4.x and earlier.</td>
</tr>
<tr>
<td width="13%" valign="top"></td>
<td width="87%" valign="top">This release requires the Visual C++ 2005
libraries. See 1.13 Known Issues for more information.</td>
</tr>
</table>
<!-- --------- --> <!-- --------- -->
<h2>JACOB 1.13</h2> <h2>JACOB 1.13</h2>
<h3>What's New</h3> <h3>What's New</h3>
@@ -82,11 +190,14 @@
<td width="100%" colspan="2"><b>Known Issues</b></td> <td width="100%" colspan="2"><b>Known Issues</b></td>
</tr> </tr>
<tr> <tr>
<td width="13%" valign="top">VC++ libraries</td> <td width="13%" valign="top"></td>
<td width="87%" valign="top">Jacob 1.13 is built using VC++ 2005. <td width="87%" valign="top">Jacob 1.13 is built using VC++ 2005.
That creates a dependency on the Visual C++ 2005 libraries and msvcr80.dll. That creates a dependency on the Visual C++ 2005 libraries and msvcr80.dll.
This library is normally installed on XP systems but may have to be manually This library is normally installed on XP systems but may have to be manually
installed on older systems. It can be obtained from the MS downloads site.</td> installed on older systems. The pagackage, often referred to as vcredist.exe
can be obtained from the MS downloads site.
If you are getting loader errors on this release or later when loading the
dll then you may be missing this library.</td>
</tr> </tr>
</table> </table>

View File

@@ -23,6 +23,16 @@ to provide a more object like API.
The only exception to this guideline is that the <code>ActiveXComponent</code> class is always The only exception to this guideline is that the <code>ActiveXComponent</code> class is always
used to make the initial connection to the target dll/COM component. used to make the initial connection to the target dll/COM component.
<hr>
<H2> Considerations when doing server side automation of office </h2>
<p>
Most office and many windows client type applications are not written to be used
in high volume or multi-threaded server environment. There is a
<a href="http://support.microsoft.com/kb/257757/">
support note </a>
on the Microsoft web site that discusses some of the issues.
<p>
<hr> <hr>
<H2> Determining the API of the target application </h2> <H2> Determining the API of the target application </h2>
<p> <p>
@@ -32,14 +42,22 @@ Section not yet written.
<h2> The Jacob DLL </h2> <h2> The Jacob DLL </h2>
<p> <p>
Jacob.jar relies on a DLL file that it loads off of the library path or classpath. Jacob.jar relies on a DLL file that it loads off of the library path or classpath.
This means that you must either copy jacob.dll into your path or use VM options to This means that you must either copy the appropriate jacob ddll into your path or
add jacob.dll directory to the path. use VM options to add directory holding jacob dll to the path. Prior to 1.14M6,
the jacob DLL name was alwasy "jacob.dll". This made it hard to verify jacob
was loading the correct dll when multiple copies of jacob were installed on a
single system. It also was confusing on 64 bit systems where the 32 bit and 64 bit
dlls have the same tames.
Starting in 1.14M6, Jacob's library
loader selects a dll with the appropriate name based on the jacob release and platform.
The dll naming convention is: <BR>
<code>jacob&lt;platform&gt;.&lt;version.&gt;.dll</code>
<p> <p>
<h3>Classloader issues</h3>
The code is written so that the jacob.dll is only loaded one time per classloader. The code is written so that the jacob.dll is only loaded one time per classloader.
This works fine in the standard application but can cause problems if jacob.jar This works fine in the standard application but can cause problems if jacob.jar
is loaded from more than one class loader. This can happen in the situation where multiple is loaded from more than one class loader. This can happen in the situation where multiple
jacob dependent web applications run in the same container like a web server or JWS runtime. jacob dependent web applications run in the same container like a web server or JWS runtime.
<p>
In the case of a web server, Jacob is normally put in the application specific WEB-INF/lib directory. In the case of a web server, Jacob is normally put in the application specific WEB-INF/lib directory.
This is the "right" way to do it and works in most situations. This is the "right" way to do it and works in most situations.
But, if Jacob is put in the WEB-INF/lib directory of each application's war file for more than But, if Jacob is put in the WEB-INF/lib directory of each application's war file for more than
@@ -71,16 +89,54 @@ oblem
Visual C redistributable installer SP1</A> Visual C redistributable installer SP1</A>
</pre> </pre>
<p> <p></p>
<hr> <hr>
<h2>Jacob Command Line Settings</h2> <h2>Jacob Command Line Settings</h2>
This library supports several different : This library supports several differentommand line options:
<h3>java.library.path</h3> <table border=1>
Used to add the location of the jacob dll to the JVM's library path. <tr><td colspan=3>
<h3>dll path location and dll name customization</h3>
</td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;</td><td valign="top">
<h4>java.library.path</h4>
</td><td>
Standard Java property used to add the location of the jacob dll to the JVM's library path.
(Added 1.11)
<p> <p>
Example: -Djava.library.path=d:/jacob/release/x86 Example: <code>-Djava.library.path=d:/jacob/release/x86</code>
</td></tr>
<h3>com.jacob.autogc </h3> <tr><td>&nbsp;&nbsp;&nbsp;</td><td valign="top">
<h4>jacob.dll.name</h4>
</td><td>
Override the standard DLL name with a custom one. This stops jacob from
using its 32bit/64bit detection and dll rendevous logic.
Sometimes used when
Jacob is bundled with another application and the application wishes
to tie the jacob dll version number to the application version numbber.
(Added 1.14M7)
<p>
Example: <code>-Djacob.dll.name=MyFunkyDllName.dll</code>
</td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;</td><td valign="top">
<h4>jacob.dll.name.x86 & jacob.dll.name.x64</h4>
</td><td>
Override the standard 32 bit DLL name with custome ones.
Sometimes used when
Jacob is bundled with another application and the application wishes
to tie the jacob dll version number to the application version numbber.
(Added 1.14M7)
<p>
Example to override 32 bit dll name: <code>-Djacob.dll.name.x86=MyFunkyDllName-32bit.dll</code>
</td></tr>
<tr><td colspan=3>
<h3>Memory Management</h3>
</td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;</td><td valign="top">
<h4>com.jacob.autogc </h4>
</td><td>
Determines if automatic garbage collection is enabled. This is the Determines if automatic garbage collection is enabled. This is the
only way to free up objects created in event callbacks. Automatic garbage collection , based on Java gc rules, garbage collection can be enabled via the only way to free up objects created in event callbacks. Automatic garbage collection , based on Java gc rules, garbage collection can be enabled via the
<code>com.java.autogc</code> command line option. <code>com.java.autogc</code> command line option.
@@ -95,16 +151,20 @@ This library supports several different :
to long running threads or to objects created as part of event callbacks. to long running threads or to objects created as part of event callbacks.
Code was added to let users try and let the JVM manage the object life cycles Code was added to let users try and let the JVM manage the object life cycles
even though the <a href="JacobComLifetime.html">JacobComLifetime.html</a> document even though the <a href="JacobComLifetime.html">JacobComLifetime.html</a> document
says this is a bad idea. says this is a bad idea. Added 1.9.
<p> <p>
<p> <p>
This value is cached at startup and cannot be changed on-the-fly via <code>System.setProperty();</code> This value is cached at startup and cannot be changed on-the-fly via <code>System.setProperty();</code>
<p> <p>
The default value is <strong>false</strong> The default value is <em>false</em>
<p> <p>
Example: <code>-Dcom.jacob.autogc=false</code> Example: <code>-Dcom.jacob.autogc=false</code>
<h3>&ltclass_name&gt.PutInROT</h3> </td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;</td><td valign="top">
<h4>&ltclass_name&gt.PutInROT</h4>
</td><td>
Lets a program specify that instances of certain classes are to not be inserted Lets a program specify that instances of certain classes are to not be inserted
into the ROT. This experimental (1.13) feature provides a mechanism for freeing into the ROT. This experimental (1.13) feature provides a mechanism for freeing
VariantViaEvent objects that are created in Event threads. There is normally no VariantViaEvent objects that are created in Event threads. There is normally no
@@ -116,7 +176,7 @@ This library supports several different :
outside of the thread it was created in but emperical evidence shows there are outside of the thread it was created in but emperical evidence shows there are
situations where this great reduces the long running memory footprint of applications situations where this great reduces the long running memory footprint of applications
that process a lot of events. <em>This function is still experimental</em>. that process a lot of events. <em>This function is still experimental</em>.
The functionality of this overlaps the experimental <code>com.jacob.autogc</code> introduced The functionality was added 1.13. Some of this overlaps the experimental <code>com.jacob.autogc</code> introduced
in 1.9. in 1.9.
See the ROT.java test program for an example of the effects of this option. See the ROT.java test program for an example of the effects of this option.
<p> <p>
@@ -126,8 +186,14 @@ This library supports several different :
Example: <code>System.setProperty("com.jacob.com.VariantViaVariant.PutInROT","false");</code> Example: <code>System.setProperty("com.jacob.com.VariantViaVariant.PutInROT","false");</code>
<BR> <BR>
Example: <code>-Dcom.jacob.com.VariantViaVariant.PutInROT=false</code> Example: <code>-Dcom.jacob.com.VariantViaVariant.PutInROT=false</code>
</td></tr>
<h3>com.jacob.debug</h3> <tr><td colspan=3>
<h3>Debugging and Troubleshooting</h3>
</td></tr>
<tr><td>&nbsp;&nbsp;&nbsp;</td><td valign="top">
<h4>com.jacob.debug</h4>
</td><td>
Determines if debug output is enabled to standard out. Determines if debug output is enabled to standard out.
<p> <p>
This value is cached at startup and cannot be changed on-the-fly via <code>System.setProperty();</code> This value is cached at startup and cannot be changed on-the-fly via <code>System.setProperty();</code>
@@ -136,14 +202,21 @@ This library supports several different :
<p> <p>
Example: <code>-Dcom.jacob.debug=false</code> Example: <code>-Dcom.jacob.debug=false</code>
</td><tr>
<h3>-XCheck:jni</h3> <tr><td>&nbsp;&nbsp;&nbsp;</td><td valign="top">
<h4>-XCheck:jni</h4>
</td><td>
This turns on additional JVM checking for JNI issues. This is This turns on additional JVM checking for JNI issues. This is
not an actual JACOB system property but a property used by the JVM. not an actual JACOB system property but a property used by the JVM.
<p> <p>
The default is "no additional checking" The default is "no additional checking"
Example: -XCheck:jni Example: <code>-XCheck:jni</code>
<p> </td></tr>
</table>
<p></p>
<hr> <hr>
<h2>Finding the DLL version using windows command line</h2> <h2>Finding the DLL version using windows command line</h2>
The jacob.dll file includes the jacob release number in the version field. The jacob.dll file includes the jacob release number in the version field.
@@ -153,8 +226,17 @@ The dll version number is stored in the "image version" field of the
This information from <a href="http://msdn2.microsoft.com/en-gb/library/h88b7dc8(VS.71).aspx"> This information from <a href="http://msdn2.microsoft.com/en-gb/library/h88b7dc8(VS.71).aspx">
The Microsoft msdn web site</a> The Microsoft msdn web site</a>
<hr>
<h2>Unit Tests</h2>
Jacob must know the location of the DLL when running the unit tests in Eclipse.
The simplest way to do this is to add the dll path to the unit as a VM argument.
The argument should be specified based on where you installed the jacob source package.
If you have jacob unpacked in d:/jacob_1_5 and built using build.xml,
then the vm arguments would be:
<br><code>-Djava.library.path=d:/jacob_1_5/release/x86</code> .
<p> <p>
Last Modified 7/2007 Last Modified 12/2007
</BODY> </BODY>
</HTML> </HTML>

View File

@@ -384,25 +384,25 @@ JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromCharArray
len = numElements(psa); len = numElements(psa);
} }
// get the double array - don't make a copy // get the double array - don't make a copy
jchar *iarr = env->GetCharArrayElements(a, 0); jchar *arrayElements = env->GetCharArrayElements(a, 0);
if (vt == VT_VARIANT) { if (vt == VT_VARIANT) {
VARIANT v; VARIANT v;
VariantInit(&v); VariantInit(&v);
V_VT(&v) = VT_UI2; V_VT(&v) = VT_UI2;
for(int i=0;i<len;i++) { for(int i=0;i<len;i++) {
V_UI2(&v) = iarr[i]; V_UI2(&v) = arrayElements[i];
long x = i; long x = i;
SafeArrayPutElement(psa,&x,&v); SafeArrayPutElement(psa,&x,&v);
} }
} else if (vt == VT_UI2 || vt == VT_I2) { } else if (vt == VT_UI2 || vt == VT_I2) {
void *pData; void *pData;
SafeArrayAccessData(psa, &pData); SafeArrayAccessData(psa, &pData);
memcpy(pData, iarr, len*sizeof(jchar)); memcpy(pData, arrayElements, len*sizeof(jchar));
SafeArrayUnaccessData(psa); SafeArrayUnaccessData(psa);
} else { } else {
ThrowComFail(env, "safearray cannot be assigned from char", 0); ThrowComFail(env, "safearray cannot be assigned from char", 0);
} }
env->ReleaseCharArrayElements(a, iarr, 0); env->ReleaseCharArrayElements(a, arrayElements, 0);
} }
/* /*
@@ -427,25 +427,68 @@ JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromIntArray
len = numElements(psa); len = numElements(psa);
} }
// get the int array - don't make a copy // get the int array - don't make a copy
jint *iarr = env->GetIntArrayElements(a, 0); jint *arrayElements = env->GetIntArrayElements(a, 0);
if (vt == VT_VARIANT) { if (vt == VT_VARIANT) {
VARIANT v; VARIANT v;
VariantInit(&v); VariantInit(&v);
V_VT(&v) = VT_I4; V_VT(&v) = VT_I4;
for(int i=0;i<len;i++) { for(int i=0;i<len;i++) {
V_I4(&v) = iarr[i]; V_I4(&v) = arrayElements[i];
long x = i; long x = i;
SafeArrayPutElement(psa,&x,&v); SafeArrayPutElement(psa,&x,&v);
} }
} else if (vt == VT_I4) { } else if (vt == VT_I4) {
void *pData; void *pData;
SafeArrayAccessData(psa, &pData); SafeArrayAccessData(psa, &pData);
memcpy(pData, iarr, len*sizeof(int)); memcpy(pData, arrayElements, len*sizeof(int));
SafeArrayUnaccessData(psa); SafeArrayUnaccessData(psa);
} else { } else {
ThrowComFail(env, "safearray cannot be assigned from int", -1); ThrowComFail(env, "safearray cannot be assigned from int", -1);
} }
env->ReleaseIntArrayElements(a, iarr, 0); env->ReleaseIntArrayElements(a, arrayElements, 0);
}
/*
* Class: SafeArray
* Method: fromLongArray
* Signature: ([L)V
*/
JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromLongArray
(JNIEnv *env, jobject _this, jlongArray a)
{
SAFEARRAY *psa = extractSA(env, _this);
if (!psa) {
ThrowComFail(env, "safearray object corrupted", -1);
return;
}
VARTYPE vt;
SafeArrayGetVartype(psa, &vt);
int len = env->GetArrayLength(a);
if (len > numElements(psa))
{
// max size of memcpy
len = numElements(psa);
}
// get the long array - don't make a copy
jlong *arrayElements = env->GetLongArrayElements(a, 0);
if (vt == VT_VARIANT) {
VARIANT v;
VariantInit(&v);
V_VT(&v) = VT_I8;
for(int i=0;i<len;i++) {
V_I8(&v) = arrayElements[i];
long x = i;
SafeArrayPutElement(psa,&x,&v);
}
} else if (vt == VT_I8) {
void *pData;
SafeArrayAccessData(psa, &pData);
memcpy(pData, arrayElements, len*sizeof(long));
SafeArrayUnaccessData(psa);
} else {
ThrowComFail(env, "safearray cannot be assigned from long", -1);
}
env->ReleaseLongArrayElements(a, arrayElements, 0);
} }
/* /*
@@ -470,25 +513,25 @@ JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromShortArray
len = numElements(psa); len = numElements(psa);
} }
// get the short array - don't make a copy // get the short array - don't make a copy
jshort *iarr = env->GetShortArrayElements(a, 0); jshort *arrayElements = env->GetShortArrayElements(a, 0);
if (vt == VT_VARIANT) { if (vt == VT_VARIANT) {
VARIANT v; VARIANT v;
VariantInit(&v); VariantInit(&v);
V_VT(&v) = VT_I2; V_VT(&v) = VT_I2;
for(int i=0;i<len;i++) { for(int i=0;i<len;i++) {
V_I2(&v) = iarr[i]; V_I2(&v) = arrayElements[i];
long x = i; long x = i;
SafeArrayPutElement(psa,&x,&v); SafeArrayPutElement(psa,&x,&v);
} }
} else if (vt == VT_I2) { } else if (vt == VT_I2) {
void *pData; void *pData;
SafeArrayAccessData(psa, &pData); SafeArrayAccessData(psa, &pData);
memcpy(pData, iarr, len*sizeof(short)); memcpy(pData, arrayElements, len*sizeof(short));
SafeArrayUnaccessData(psa); SafeArrayUnaccessData(psa);
} else { } else {
ThrowComFail(env, "safearray cannot be assigned from short", -1); ThrowComFail(env, "safearray cannot be assigned from short", -1);
} }
env->ReleaseShortArrayElements(a, iarr, 0); env->ReleaseShortArrayElements(a, arrayElements, 0);
} }
/* /*
@@ -513,25 +556,25 @@ JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromDoubleArray
len = numElements(psa); len = numElements(psa);
} }
// get the double array - don't make a copy // get the double array - don't make a copy
jdouble *iarr = env->GetDoubleArrayElements(a, 0); jdouble *arrayElements = env->GetDoubleArrayElements(a, 0);
if (vt == VT_VARIANT) { if (vt == VT_VARIANT) {
VARIANT v; VARIANT v;
VariantInit(&v); VariantInit(&v);
V_VT(&v) = VT_R8; V_VT(&v) = VT_R8;
for(int i=0;i<len;i++) { for(int i=0;i<len;i++) {
V_R8(&v) = iarr[i]; V_R8(&v) = arrayElements[i];
long x = i; long x = i;
SafeArrayPutElement(psa,&x,&v); SafeArrayPutElement(psa,&x,&v);
} }
} else if (vt == VT_R8 || vt == VT_DATE) { } else if (vt == VT_R8 || vt == VT_DATE) {
void *pData; void *pData;
SafeArrayAccessData(psa, &pData); SafeArrayAccessData(psa, &pData);
memcpy(pData, iarr, len*sizeof(double)); memcpy(pData, arrayElements, len*sizeof(double));
SafeArrayUnaccessData(psa); SafeArrayUnaccessData(psa);
} else { } else {
ThrowComFail(env, "safearray cannot be assigned from double", -1); ThrowComFail(env, "safearray cannot be assigned from double", -1);
} }
env->ReleaseDoubleArrayElements(a, iarr, 0); env->ReleaseDoubleArrayElements(a, arrayElements, 0);
} }
/* /*
@@ -613,25 +656,25 @@ JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromByteArray
len = numElements(psa); len = numElements(psa);
} }
// get the byte array - don't make a copy // get the byte array - don't make a copy
jbyte *iarr = env->GetByteArrayElements(a, 0); jbyte *arrayElements = env->GetByteArrayElements(a, 0);
if (vt == VT_VARIANT) { if (vt == VT_VARIANT) {
VARIANT v; VARIANT v;
VariantInit(&v); VariantInit(&v);
V_VT(&v) = VT_UI1; V_VT(&v) = VT_UI1;
for(int i=0;i<len;i++) { for(int i=0;i<len;i++) {
V_UI1(&v) = iarr[i]; V_UI1(&v) = arrayElements[i];
long x = i; long x = i;
SafeArrayPutElement(psa,&x,&v); SafeArrayPutElement(psa,&x,&v);
} }
} else if (vt == VT_UI1 || vt == VT_I1) { } else if (vt == VT_UI1 || vt == VT_I1) {
jbyte *pData; jbyte *pData;
SafeArrayAccessData(psa, (void **)&pData); SafeArrayAccessData(psa, (void **)&pData);
memcpy(pData, iarr, len*sizeof(jbyte)); memcpy(pData, arrayElements, len*sizeof(jbyte));
SafeArrayUnaccessData(psa); SafeArrayUnaccessData(psa);
} else { } else {
ThrowComFail(env, "safearray cannot be assigned from byte", -1); ThrowComFail(env, "safearray cannot be assigned from byte", -1);
} }
env->ReleaseByteArrayElements(a, iarr, 0); env->ReleaseByteArrayElements(a, arrayElements, 0);
} }
/* /*
@@ -656,25 +699,25 @@ JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromFloatArray
len = numElements(psa); len = numElements(psa);
} }
// get the float array - don't make a copy // get the float array - don't make a copy
jfloat *iarr = env->GetFloatArrayElements(a, 0); jfloat *arrayElements = env->GetFloatArrayElements(a, 0);
if (vt == VT_VARIANT) { if (vt == VT_VARIANT) {
VARIANT v; VARIANT v;
VariantInit(&v); VariantInit(&v);
V_VT(&v) = VT_R4; V_VT(&v) = VT_R4;
for(int i=0;i<len;i++) { for(int i=0;i<len;i++) {
V_R4(&v) = iarr[i]; V_R4(&v) = arrayElements[i];
long x = i; long x = i;
SafeArrayPutElement(psa,&x,&v); SafeArrayPutElement(psa,&x,&v);
} }
} else if (vt == VT_R4) { } else if (vt == VT_R4) {
void *pData; void *pData;
SafeArrayAccessData(psa, &pData); SafeArrayAccessData(psa, &pData);
memcpy(pData, iarr, len*sizeof(float)); memcpy(pData, arrayElements, len*sizeof(float));
SafeArrayUnaccessData(psa); SafeArrayUnaccessData(psa);
} else { } else {
ThrowComFail(env, "safearray cannot be assigned from float", -1); ThrowComFail(env, "safearray cannot be assigned from float", -1);
} }
env->ReleaseFloatArrayElements(a, iarr, 0); env->ReleaseFloatArrayElements(a, arrayElements, 0);
} }
/* /*
@@ -699,13 +742,13 @@ JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromBooleanArray
len = numElements(psa); len = numElements(psa);
} }
// get the boolean array - don't make a copy // get the boolean array - don't make a copy
jboolean *iarr = env->GetBooleanArrayElements(a, 0); jboolean *arrayElements = env->GetBooleanArrayElements(a, 0);
if (vt == VT_VARIANT) { if (vt == VT_VARIANT) {
VARIANT v; VARIANT v;
VariantInit(&v); VariantInit(&v);
V_VT(&v) = VT_BOOL; V_VT(&v) = VT_BOOL;
for(int i=0;i<len;i++) { for(int i=0;i<len;i++) {
V_BOOL(&v) = iarr[i] ? VARIANT_TRUE : VARIANT_FALSE; V_BOOL(&v) = arrayElements[i] ? VARIANT_TRUE : VARIANT_FALSE;
long x = i; long x = i;
SafeArrayPutElement(psa,&x,&v); SafeArrayPutElement(psa,&x,&v);
} }
@@ -713,14 +756,14 @@ JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromBooleanArray
// jboolean is 1 byte and VARIANT_BOOL is 2 // jboolean is 1 byte and VARIANT_BOOL is 2
VARIANT_BOOL v; VARIANT_BOOL v;
for(int i=0;i<len;i++) { for(int i=0;i<len;i++) {
v = iarr[i] ? VARIANT_TRUE : VARIANT_FALSE; v = arrayElements[i] ? VARIANT_TRUE : VARIANT_FALSE;
long x = i; long x = i;
SafeArrayPutElement(psa,&x,&v); SafeArrayPutElement(psa,&x,&v);
} }
} else { } else {
ThrowComFail(env, "safearray cannot be assigned from boolean", -1); ThrowComFail(env, "safearray cannot be assigned from boolean", -1);
} }
env->ReleaseBooleanArrayElements(a, iarr, 0); env->ReleaseBooleanArrayElements(a, arrayElements, 0);
} }
/* /*
@@ -776,14 +819,14 @@ JNIEXPORT jcharArray JNICALL Java_com_jacob_com_SafeArray_toCharArray
VARTYPE vt; VARTYPE vt;
SafeArrayGetVartype(sa, &vt); SafeArrayGetVartype(sa, &vt);
if (vt == VT_UI2 || vt == VT_I2) { if (vt == VT_UI2 || vt == VT_I2) {
jcharArray iarr = env->NewCharArray(num); jcharArray arrayElements = env->NewCharArray(num);
void *pData; void *pData;
SafeArrayAccessData(sa, &pData); SafeArrayAccessData(sa, &pData);
env->SetCharArrayRegion(iarr, 0, num, (jchar *)pData); env->SetCharArrayRegion(arrayElements, 0, num, (jchar *)pData);
SafeArrayUnaccessData(sa); SafeArrayUnaccessData(sa);
return iarr; return arrayElements;
} else if (vt == VT_VARIANT) { } else if (vt == VT_VARIANT) {
jcharArray iarr = env->NewCharArray(num); jcharArray arrayElements = env->NewCharArray(num);
VARIANT v; VARIANT v;
VariantInit(&v); VariantInit(&v);
for(int i=lb;i<=ub;i++) { for(int i=lb;i<=ub;i++) {
@@ -793,9 +836,9 @@ JNIEXPORT jcharArray JNICALL Java_com_jacob_com_SafeArray_toCharArray
return NULL; return NULL;
} }
jchar val = V_UI2(&v); jchar val = V_UI2(&v);
env->SetCharArrayRegion(iarr, i, 1, &val); env->SetCharArrayRegion(arrayElements, i, 1, &val);
} }
return iarr; return arrayElements;
} }
return NULL; return NULL;
} }
@@ -820,14 +863,14 @@ JNIEXPORT jintArray JNICALL Java_com_jacob_com_SafeArray_toIntArray
VARTYPE vt; VARTYPE vt;
SafeArrayGetVartype(sa, &vt); SafeArrayGetVartype(sa, &vt);
if (vt == VT_I4) { if (vt == VT_I4) {
jintArray iarr = env->NewIntArray(num); jintArray arrayElements = env->NewIntArray(num);
void *pData; void *pData;
SafeArrayAccessData(sa, &pData); SafeArrayAccessData(sa, &pData);
env->SetIntArrayRegion(iarr, 0, num, (jint *)pData); env->SetIntArrayRegion(arrayElements, 0, num, (jint *)pData);
SafeArrayUnaccessData(sa); SafeArrayUnaccessData(sa);
return iarr; return arrayElements;
} else if (vt == VT_VARIANT) { } else if (vt == VT_VARIANT) {
jintArray iarr = env->NewIntArray(num); jintArray arrayElements = env->NewIntArray(num);
VARIANT v; VARIANT v;
VariantInit(&v); VariantInit(&v);
for(int i=lb;i<=ub;i++) { for(int i=lb;i<=ub;i++) {
@@ -837,9 +880,54 @@ JNIEXPORT jintArray JNICALL Java_com_jacob_com_SafeArray_toIntArray
return NULL; return NULL;
} }
jint val = V_I4(&v); jint val = V_I4(&v);
env->SetIntArrayRegion(iarr, i, 1, &val); env->SetIntArrayRegion(arrayElements, i, 1, &val);
} }
return iarr; return arrayElements;
}
return NULL;
}
/*
* Class: SafeArray
* Method: toLongArray
* Signature: ()[L
*/
JNIEXPORT jlongArray JNICALL Java_com_jacob_com_SafeArray_toLongArray
(JNIEnv *env, jobject _this)
{
SAFEARRAY *sa = extractSA(env, _this);
if (!sa) {
ThrowComFail(env, "safearray object corrupted", -1);
return NULL;
}
long lb, ub;
SafeArrayGetLBound(sa, 1, &lb);
SafeArrayGetUBound(sa, 1, &ub);
int num = ub - lb + 1;
VARTYPE vt;
SafeArrayGetVartype(sa, &vt);
if (vt == VT_I8) {
jlongArray arrayElements = env->NewLongArray(num);
void *pData;
SafeArrayAccessData(sa, &pData);
env->SetLongArrayRegion(arrayElements, 0, num, (jlong *)pData);
SafeArrayUnaccessData(sa);
return arrayElements;
} else if (vt == VT_VARIANT) {
jlongArray arrayElements = env->NewLongArray(num);
VARIANT v;
VariantInit(&v);
for(int i=lb;i<=ub;i++) {
long ix = i;
SafeArrayGetElement(sa, &ix, (void*) &v);
if (FAILED(VariantChangeType(&v, &v, 0, VT_I8))) {
return NULL;
}
jlong val = V_I8(&v);
env->SetLongArrayRegion(arrayElements, i, 1, &val);
}
return arrayElements;
} }
return NULL; return NULL;
} }
@@ -865,14 +953,14 @@ JNIEXPORT jshortArray JNICALL Java_com_jacob_com_SafeArray_toShortArray
VARTYPE vt; VARTYPE vt;
SafeArrayGetVartype(sa, &vt); SafeArrayGetVartype(sa, &vt);
if (vt == VT_I2) { if (vt == VT_I2) {
jshortArray iarr = env->NewShortArray(num); jshortArray arrayElements = env->NewShortArray(num);
void *pData; void *pData;
SafeArrayAccessData(sa, &pData); SafeArrayAccessData(sa, &pData);
env->SetShortArrayRegion(iarr, 0, num, (jshort *)pData); env->SetShortArrayRegion(arrayElements, 0, num, (jshort *)pData);
SafeArrayUnaccessData(sa); SafeArrayUnaccessData(sa);
return iarr; return arrayElements;
} else if (vt == VT_VARIANT) { } else if (vt == VT_VARIANT) {
jshortArray iarr = env->NewShortArray(num); jshortArray arrayElements = env->NewShortArray(num);
VARIANT v; VARIANT v;
VariantInit(&v); VariantInit(&v);
for(int i=lb;i<=ub;i++) { for(int i=lb;i<=ub;i++) {
@@ -882,9 +970,9 @@ JNIEXPORT jshortArray JNICALL Java_com_jacob_com_SafeArray_toShortArray
return NULL; return NULL;
} }
jshort val = V_I2(&v); jshort val = V_I2(&v);
env->SetShortArrayRegion(iarr, i, 1, &val); env->SetShortArrayRegion(arrayElements, i, 1, &val);
} }
return iarr; return arrayElements;
} }
return NULL; return NULL;
} }
@@ -909,14 +997,14 @@ JNIEXPORT jdoubleArray JNICALL Java_com_jacob_com_SafeArray_toDoubleArray
VARTYPE vt; VARTYPE vt;
SafeArrayGetVartype(sa, &vt); SafeArrayGetVartype(sa, &vt);
if (vt == VT_R8) { if (vt == VT_R8) {
jdoubleArray iarr = env->NewDoubleArray(num); jdoubleArray arrayElements = env->NewDoubleArray(num);
void *pData; void *pData;
SafeArrayAccessData(sa, &pData); SafeArrayAccessData(sa, &pData);
env->SetDoubleArrayRegion(iarr, 0, num, (jdouble *)pData); env->SetDoubleArrayRegion(arrayElements, 0, num, (jdouble *)pData);
SafeArrayUnaccessData(sa); SafeArrayUnaccessData(sa);
return iarr; return arrayElements;
} else if (vt == VT_VARIANT) { } else if (vt == VT_VARIANT) {
jdoubleArray iarr = env->NewDoubleArray(num); jdoubleArray arrayElements = env->NewDoubleArray(num);
VARIANT v; VARIANT v;
VariantInit(&v); VariantInit(&v);
for(int i=lb;i<=ub;i++) { for(int i=lb;i<=ub;i++) {
@@ -926,9 +1014,9 @@ JNIEXPORT jdoubleArray JNICALL Java_com_jacob_com_SafeArray_toDoubleArray
return NULL; return NULL;
} }
jdouble val = V_R8(&v); jdouble val = V_R8(&v);
env->SetDoubleArrayRegion(iarr, i, 1, &val); env->SetDoubleArrayRegion(arrayElements, i, 1, &val);
} }
return iarr; return arrayElements;
} }
return NULL; return NULL;
} }
@@ -955,7 +1043,7 @@ JNIEXPORT jobjectArray JNICALL Java_com_jacob_com_SafeArray_toStringArray
if (vt == VT_VARIANT) if (vt == VT_VARIANT)
{ {
jclass sClass = env->FindClass("java/lang/String"); jclass sClass = env->FindClass("java/lang/String");
jobjectArray iarr = env->NewObjectArray(num, sClass, NULL); jobjectArray arrayElements = env->NewObjectArray(num, sClass, NULL);
VARIANT v; VARIANT v;
VariantInit(&v); VariantInit(&v);
for(int i=lb;i<=ub;i++) { for(int i=lb;i<=ub;i++) {
@@ -966,20 +1054,20 @@ JNIEXPORT jobjectArray JNICALL Java_com_jacob_com_SafeArray_toStringArray
} }
BSTR bs = V_BSTR(&v); BSTR bs = V_BSTR(&v);
jstring js = env->NewString((jchar*)bs, SysStringLen(bs)); // SR cast SF 1689061 jstring js = env->NewString((jchar*)bs, SysStringLen(bs)); // SR cast SF 1689061
env->SetObjectArrayElement(iarr, i, js); env->SetObjectArrayElement(arrayElements, i, js);
} }
return iarr; return arrayElements;
} else if (vt == VT_BSTR) { } else if (vt == VT_BSTR) {
jclass sClass = env->FindClass("java/lang/String"); jclass sClass = env->FindClass("java/lang/String");
jobjectArray iarr = env->NewObjectArray(num, sClass, NULL); jobjectArray arrayElements = env->NewObjectArray(num, sClass, NULL);
for(int i=lb;i<=ub;i++) { for(int i=lb;i<=ub;i++) {
BSTR bs = NULL; BSTR bs = NULL;
long ix = i; long ix = i;
SafeArrayGetElement(sa, &ix, (void*) &bs); SafeArrayGetElement(sa, &ix, (void*) &bs);
jstring js = env->NewString((jchar*)bs, SysStringLen(bs)); // SR cast SF 1689061 jstring js = env->NewString((jchar*)bs, SysStringLen(bs)); // SR cast SF 1689061
env->SetObjectArrayElement(iarr, i, js); env->SetObjectArrayElement(arrayElements, i, js);
} }
return iarr; return arrayElements;
} }
ThrowComFail(env, "safearray cannot be converted to string[]", 0); ThrowComFail(env, "safearray cannot be converted to string[]", 0);
return NULL; return NULL;
@@ -1005,14 +1093,14 @@ JNIEXPORT jbyteArray JNICALL Java_com_jacob_com_SafeArray_toByteArray
VARTYPE vt; VARTYPE vt;
SafeArrayGetVartype(sa, &vt); SafeArrayGetVartype(sa, &vt);
if (vt == VT_I1 || vt == VT_UI1) { if (vt == VT_I1 || vt == VT_UI1) {
jbyteArray iarr = env->NewByteArray(num); jbyteArray arrayElements = env->NewByteArray(num);
jbyte *pData; jbyte *pData;
SafeArrayAccessData(sa, (void **)&pData); SafeArrayAccessData(sa, (void **)&pData);
env->SetByteArrayRegion(iarr, 0, num, pData); env->SetByteArrayRegion(arrayElements, 0, num, pData);
SafeArrayUnaccessData(sa); SafeArrayUnaccessData(sa);
return iarr; return arrayElements;
} else if (vt == VT_VARIANT) { } else if (vt == VT_VARIANT) {
jbyteArray iarr = env->NewByteArray(num); jbyteArray arrayElements = env->NewByteArray(num);
VARIANT v; VARIANT v;
VariantInit(&v); VariantInit(&v);
for(int i=lb,j=0;i<=ub;i++,j++) { for(int i=lb,j=0;i<=ub;i++,j++) {
@@ -1022,9 +1110,9 @@ JNIEXPORT jbyteArray JNICALL Java_com_jacob_com_SafeArray_toByteArray
return NULL; return NULL;
} }
jbyte val = V_UI1(&v); jbyte val = V_UI1(&v);
env->SetByteArrayRegion(iarr, j, 1, &val); env->SetByteArrayRegion(arrayElements, j, 1, &val);
} }
return iarr; return arrayElements;
} }
return NULL; return NULL;
} }
@@ -1049,14 +1137,14 @@ JNIEXPORT jfloatArray JNICALL Java_com_jacob_com_SafeArray_toFloatArray
VARTYPE vt; VARTYPE vt;
SafeArrayGetVartype(sa, &vt); SafeArrayGetVartype(sa, &vt);
if (vt == VT_R4) { if (vt == VT_R4) {
jfloatArray iarr = env->NewFloatArray(num); jfloatArray arrayElements = env->NewFloatArray(num);
void *pData; void *pData;
SafeArrayAccessData(sa, &pData); SafeArrayAccessData(sa, &pData);
env->SetFloatArrayRegion(iarr, 0, num, (jfloat *)pData); env->SetFloatArrayRegion(arrayElements, 0, num, (jfloat *)pData);
SafeArrayUnaccessData(sa); SafeArrayUnaccessData(sa);
return iarr; return arrayElements;
} else if (vt == VT_VARIANT) { } else if (vt == VT_VARIANT) {
jfloatArray iarr = env->NewFloatArray(num); jfloatArray arrayElements = env->NewFloatArray(num);
VARIANT v; VARIANT v;
VariantInit(&v); VariantInit(&v);
for(int i=lb;i<=ub;i++) { for(int i=lb;i<=ub;i++) {
@@ -1066,9 +1154,9 @@ JNIEXPORT jfloatArray JNICALL Java_com_jacob_com_SafeArray_toFloatArray
return NULL; return NULL;
} }
jfloat val = V_R4(&v); jfloat val = V_R4(&v);
env->SetFloatArrayRegion(iarr, i, 1, &val); env->SetFloatArrayRegion(arrayElements, i, 1, &val);
} }
return iarr; return arrayElements;
} }
return NULL; return NULL;
} }
@@ -1094,17 +1182,17 @@ JNIEXPORT jbooleanArray JNICALL Java_com_jacob_com_SafeArray_toBooleanArray
SafeArrayGetVartype(sa, &vt); SafeArrayGetVartype(sa, &vt);
if (vt == VT_BOOL) { if (vt == VT_BOOL) {
// need to loop because jboolean=1 byte and VARIANT_BOOL=2 bytes // need to loop because jboolean=1 byte and VARIANT_BOOL=2 bytes
jbooleanArray iarr = env->NewBooleanArray(num); jbooleanArray arrayElements = env->NewBooleanArray(num);
VARIANT_BOOL v; VARIANT_BOOL v;
for(int i=lb,j=0;i<=ub;i++,j++) { for(int i=lb,j=0;i<=ub;i++,j++) {
long ix = i; long ix = i;
SafeArrayGetElement(sa, &ix, (void*) &v); SafeArrayGetElement(sa, &ix, (void*) &v);
jboolean val = v == VARIANT_TRUE ? JNI_TRUE : JNI_FALSE; jboolean val = v == VARIANT_TRUE ? JNI_TRUE : JNI_FALSE;
env->SetBooleanArrayRegion(iarr, j, 1, &val); env->SetBooleanArrayRegion(arrayElements, j, 1, &val);
} }
return iarr; return arrayElements;
} else if (vt == VT_VARIANT) { } else if (vt == VT_VARIANT) {
jbooleanArray iarr = env->NewBooleanArray(num); jbooleanArray arrayElements = env->NewBooleanArray(num);
VARIANT v; VARIANT v;
VariantInit(&v); VariantInit(&v);
for(int i=lb;i<=ub;i++) { for(int i=lb;i<=ub;i++) {
@@ -1114,9 +1202,9 @@ JNIEXPORT jbooleanArray JNICALL Java_com_jacob_com_SafeArray_toBooleanArray
return NULL; return NULL;
} }
jboolean val = V_BOOL(&v) == VARIANT_TRUE ? JNI_TRUE : JNI_FALSE; jboolean val = V_BOOL(&v) == VARIANT_TRUE ? JNI_TRUE : JNI_FALSE;
env->SetBooleanArrayRegion(iarr, i, 1, &val); env->SetBooleanArrayRegion(arrayElements, i, 1, &val);
} }
return iarr; return arrayElements;
} }
return NULL; return NULL;
} }
@@ -1310,25 +1398,25 @@ JNIEXPORT jobjectArray JNICALL Java_com_jacob_com_SafeArray_toVariantArray
} \ } \
VARTYPE vt; \ VARTYPE vt; \
SafeArrayGetVartype(psa, &vt); \ SafeArrayGetVartype(psa, &vt); \
jtyp *iarr = env->jgetArr(ja, 0); \ jtyp *arrayElements = env->jgetArr(ja, 0); \
if (vt == VT_VARIANT) { \ if (vt == VT_VARIANT) { \
VARIANT v; \ VARIANT v; \
VariantInit(&v); \ VariantInit(&v); \
V_VT(&v) = varType; \ V_VT(&v) = varType; \
for(int i=ja_start,j=idx;i<ja_start+nelem;i++,j++) { \ for(int i=ja_start,j=idx;i<ja_start+nelem;i++,j++) { \
varAccess(&v) = iarr[i]; \ varAccess(&v) = arrayElements[i]; \
long x = j; \ long x = j; \
SafeArrayPutElement(psa,&x,&v); \ SafeArrayPutElement(psa,&x,&v); \
} \ } \
} else if (vt == varType || vt == varType2) { \ } else if (vt == varType || vt == varType2) { \
jtyp *pData; \ jtyp *pData; \
SafeArrayAccessData(psa, (void **)&pData); \ SafeArrayAccessData(psa, (void **)&pData); \
memcpy(&pData[idx], &iarr[ja_start], nelem*sizeof(jtyp)); \ memcpy(&pData[idx], &arrayElements[ja_start], nelem*sizeof(jtyp)); \
SafeArrayUnaccessData(psa); \ SafeArrayUnaccessData(psa); \
} else { \ } else { \
ThrowComFail(env, "safearray type mismatch", -1); \ ThrowComFail(env, "safearray type mismatch", -1); \
} \ } \
env->jrelArr(ja, iarr, 0); env->jrelArr(ja, arrayElements, 0);
/* /*
* Class: SafeArray * Class: SafeArray
@@ -1398,6 +1486,8 @@ JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setChars
GetCharArrayElements, ReleaseCharArrayElements); GetCharArrayElements, ReleaseCharArrayElements);
} }
/*----------------------- INTS ----------------------------------*/
/* /*
* Class: SafeArray * Class: SafeArray
* Method: getInt * Method: getInt
@@ -1465,6 +1555,79 @@ JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setInts
GetIntArrayElements, ReleaseIntArrayElements); GetIntArrayElements, ReleaseIntArrayElements);
} }
/*----------------------- END INTS ----------------------------------*/
/*----------------------- LONGS ----------------------------------*/
/*
* Class: SafeArray
* Method: getLong
* Signature: (I)J
*/
JNIEXPORT jlong JNICALL Java_com_jacob_com_SafeArray_getLong__I
(JNIEnv *env, jobject _this, jint idx)
{
GET1DCODE(VT_I8, V_I8, jlong)
}
/*
* Class: SafeArray
* Method: getLong
* Signature: (II)J
*/
JNIEXPORT jlong JNICALL Java_com_jacob_com_SafeArray_getLong__II
(JNIEnv *env, jobject _this, jint i, jint j)
{
GET2DCODE(VT_I8, V_I8, jlong)
}
/*
* Class: SafeArray
* Method: setLong
* Signature: (IJ)V
*/
JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setLong__IJ
(JNIEnv *env, jobject _this, jint idx, jlong c)
{
SET1DCODE(VT_I8, V_I8);
}
/*
* Class: SafeArray
* Method: setLong
* Signature: (IIJ)V
*/
JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setLong__IIJ
(JNIEnv *env, jobject _this, jint i, jint j, jlong c)
{
SET2DCODE(VT_I8, V_I8);
}
/*
* Class: SafeArray
* Method: getLongs
* Signature: (II[JI)V
*/
JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_getLongs
(JNIEnv *env, jobject _this, jint idx, jint nelem, jlongArray ja, jint ja_start)
{
GETARRAYCODE(VT_I8, VT_I8, V_I8, jlong, SetLongArrayRegion);
}
/*
* Class: SafeArray
* Method: setLongs
* Signature: (II[JI)V
*/
JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setLongs
(JNIEnv *env, jobject _this, jint idx, jint nelem, jlongArray ja, jint ja_start)
{
SETARRAYCODE(VT_I8, VT_I8, V_I8, jlong,
GetLongArrayElements, ReleaseLongArrayElements);
}
/*------------------------ END LONGS -----------------------------*/
/* /*
* Class: SafeArray * Class: SafeArray
* Method: getShort * Method: getShort
@@ -2206,27 +2369,27 @@ JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setBooleans
{ {
len = numElements(psa); len = numElements(psa);
} }
jboolean *iarr = env->GetBooleanArrayElements(ja, 0); jboolean *arrayElements = env->GetBooleanArrayElements(ja, 0);
if (vt == VT_VARIANT) { if (vt == VT_VARIANT) {
VARIANT v; VARIANT v;
VariantInit(&v); VariantInit(&v);
V_VT(&v) = VT_BOOL; V_VT(&v) = VT_BOOL;
for(int i=ja_start,j=idx;i<ja_start+nelem;i++,j++) { for(int i=ja_start,j=idx;i<ja_start+nelem;i++,j++) {
V_BOOL(&v) = iarr[i] == JNI_TRUE ? VARIANT_TRUE : VARIANT_FALSE; V_BOOL(&v) = arrayElements[i] == JNI_TRUE ? VARIANT_TRUE : VARIANT_FALSE;
long x = j; long x = j;
SafeArrayPutElement(psa,&x,&v); SafeArrayPutElement(psa,&x,&v);
} }
} else if (vt == VT_BOOL) { } else if (vt == VT_BOOL) {
VARIANT_BOOL v; VARIANT_BOOL v;
for(int i=ja_start,j=idx;i<ja_start+nelem;i++,j++) { for(int i=ja_start,j=idx;i<ja_start+nelem;i++,j++) {
v = iarr[i] == JNI_TRUE ? VARIANT_TRUE : VARIANT_FALSE; v = arrayElements[i] == JNI_TRUE ? VARIANT_TRUE : VARIANT_FALSE;
long x = j; long x = j;
SafeArrayPutElement(psa,&x,&v); SafeArrayPutElement(psa,&x,&v);
} }
} else { } else {
ThrowComFail(env, "safearray type mismatch", -1); ThrowComFail(env, "safearray type mismatch", -1);
} }
env->ReleaseBooleanArrayElements(ja, iarr, 0); env->ReleaseBooleanArrayElements(ja, arrayElements, 0);
} }
/* /*
@@ -2660,6 +2823,8 @@ JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setChar___3IC
SETNDCODE(VT_UI2, V_UI2); SETNDCODE(VT_UI2, V_UI2);
} }
/*----------------------- INTS ----------------------------------*/
/* /*
* Class: com_jacob_com_SafeArray * Class: com_jacob_com_SafeArray
* Method: getInt * Method: getInt
@@ -2683,6 +2848,34 @@ JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setInt___3II
SETNDCODE(VT_I4, V_I4); SETNDCODE(VT_I4, V_I4);
} }
/*----------------------- END INTS ----------------------------------*/
/*----------------------- LONGS ----------------------------------*/
/*
* Class: com_jacob_com_SafeArray
* Method: getLong
* Signature: ([I)J
*/
JNIEXPORT jlong JNICALL Java_com_jacob_com_SafeArray_getLong___3I
(JNIEnv *env, jobject _this, jintArray indices)
{
GETNDCODE(VT_I8, V_I8, jlong)
}
/*
* Class: com_jacob_com_SafeArray
* Method: setLong
* Signature: ([IJ)V
*/
JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setLong___3IJ
(JNIEnv *env, jobject _this, jintArray indices, jlong c)
{
SETNDCODE(VT_I8, V_I8);
}
/*----------------------- END LONGS ----------------------------------*/
/* /*
* Class: com_jacob_com_SafeArray * Class: com_jacob_com_SafeArray
* Method: getShort * Method: getShort

View File

@@ -149,6 +149,14 @@ JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromCharArray
JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromIntArray JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromIntArray
(JNIEnv *, jobject, jintArray); (JNIEnv *, jobject, jintArray);
/*
* Class: com_jacob_com_SafeArray
* Method: fromLongArray
* Signature: ([L)V
*/
JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromLongArray
(JNIEnv *, jobject, jlongArray);
/* /*
* Class: com_jacob_com_SafeArray * Class: com_jacob_com_SafeArray
* Method: fromShortArray * Method: fromShortArray
@@ -221,6 +229,14 @@ JNIEXPORT jcharArray JNICALL Java_com_jacob_com_SafeArray_toCharArray
JNIEXPORT jintArray JNICALL Java_com_jacob_com_SafeArray_toIntArray JNIEXPORT jintArray JNICALL Java_com_jacob_com_SafeArray_toIntArray
(JNIEnv *, jobject); (JNIEnv *, jobject);
/*
* Class: com_jacob_com_SafeArray
* Method: toLongArray
* Signature: ()[L
*/
JNIEXPORT jlongArray JNICALL Java_com_jacob_com_SafeArray_toLongArray
(JNIEnv *, jobject);
/* /*
* Class: com_jacob_com_SafeArray * Class: com_jacob_com_SafeArray
* Method: toShortArray * Method: toShortArray
@@ -373,6 +389,54 @@ JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_getInts
JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setInts JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setInts
(JNIEnv *, jobject, jint, jint, jintArray, jint); (JNIEnv *, jobject, jint, jint, jintArray, jint);
/*
* Class: SafeArray
* Method: getLong
* Signature: (I)J
*/
JNIEXPORT jlong JNICALL Java_com_jacob_com_SafeArray_getLong__I
(JNIEnv *env, jobject _this, jint idx);
/*
* Class: SafeArray
* Method: getLong
* Signature: (II)J
*/
JNIEXPORT jlong JNICALL Java_com_jacob_com_SafeArray_getLong__II
(JNIEnv *env, jobject _this, jint i, jint j);
/*
* Class: SafeArray
* Method: setLong
* Signature: (IJ)V
*/
JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setLong__IJ
(JNIEnv *env, jobject _this, jint idx, jlong c);
/*
* Class: SafeArray
* Method: setLong
* Signature: (IIJ)V
*/
JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setLong__IIJ
(JNIEnv *env, jobject _this, jint i, jint j, jlong c);
/*
* Class: SafeArray
* Method: getLongs
* Signature: (II[JI)V
*/
JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_getLongs
(JNIEnv *env, jobject _this, jint idx, jint nelem, jlongArray ja, jint ja_start);
/*
* Class: SafeArray
* Method: setLongs
* Signature: (II[JI)V
*/
JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setLongs
(JNIEnv *env, jobject _this, jint idx, jint nelem, jlongArray ja, jint ja_start);
/* /*
* Class: com_jacob_com_SafeArray * Class: com_jacob_com_SafeArray
* Method: getShort * Method: getShort
@@ -757,6 +821,23 @@ JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getInt___3I
JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setInt___3II JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setInt___3II
(JNIEnv *, jobject, jintArray, jint); (JNIEnv *, jobject, jintArray, jint);
/*
* Class: com_jacob_com_SafeArray
* Method: getLong
* Signature: ([I)J
*/
JNIEXPORT jlong JNICALL Java_com_jacob_com_SafeArray_getLong___3I
(JNIEnv *env, jobject _this, jintArray indices);
/*
* Class: com_jacob_com_SafeArray
* Method: setLong
* Signature: ([IJ)V
*/
JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setLong___3IJ
(JNIEnv *env, jobject _this, jintArray indices, jlong c);
/* /*
* Class: com_jacob_com_SafeArray * Class: com_jacob_com_SafeArray
* Method: getShort * Method: getShort

View File

@@ -611,6 +611,17 @@ JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantCurrency
} else ThrowComFail(env, "putVariantCurrency failed", -1); } else ThrowComFail(env, "putVariantCurrency failed", -1);
} }
JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantLong
(JNIEnv *env, jobject _this, jlong longValue)
{
VARIANT *v = extractVariant(env, _this);
if (v) {
VariantClear(v); // whatever was there before
V_VT(v) = VT_I8;
V_I8(v) = (LONGLONG)longValue;
} else ThrowComFail(env, "putVariantLong failed", -1);
}
/** /**
* Accepts a dispatch object and sets the type to VT_DISPATCH. * Accepts a dispatch object and sets the type to VT_DISPATCH.
* There is currently no way to pass NULL into this method * There is currently no way to pass NULL into this method
@@ -662,6 +673,18 @@ JNIEXPORT jlong JNICALL Java_com_jacob_com_Variant_getVariantCurrency
return NULL; return NULL;
} }
JNIEXPORT jlong JNICALL Java_com_jacob_com_Variant_getVariantLong
(JNIEnv *env, jobject _this)
{
VARIANT *v = extractVariant(env, _this);
if (v) {
if (V_VT(v) != VT_I8) {
return NULL;
}
return (jlong)V_I8(v);
}
return NULL;
}
JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantFloatRef JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantFloatRef
(JNIEnv *env, jobject _this, jfloat val) (JNIEnv *env, jobject _this, jfloat val)
@@ -689,6 +712,19 @@ JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantCurrencyRef
} }
} }
JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantLongRef
(JNIEnv *env, jobject _this, jlong longValue)
{
VARIANT *v = extractVariant(env, _this);
if (v) {
VariantClear(v); // whatever was there before
LONGLONG *ps = (LONGLONG *)CoTaskMemAlloc(sizeof(LONGLONG));
*ps = longValue;
V_VT(v) = VT_I8|VT_BYREF;
V_I8REF(v) = ps;
}
}
JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantErrorRef JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantErrorRef
(JNIEnv *env, jobject _this, jint i) (JNIEnv *env, jobject _this, jint i)
{ {
@@ -801,6 +837,19 @@ JNIEXPORT jlong JNICALL Java_com_jacob_com_Variant_getVariantCurrencyRef
return NULL; return NULL;
} }
JNIEXPORT jlong JNICALL Java_com_jacob_com_Variant_getVariantLongRef
(JNIEnv *env, jobject _this)
{
VARIANT *v = extractVariant(env, _this);
if (v) {
if (V_VT(v) != (VT_I8|VT_BYREF)) {
return NULL;
}
return (jlong)*V_I8REF(v);
}
return NULL;
}
JNIEXPORT jint JNICALL Java_com_jacob_com_Variant_getVariantErrorRef JNIEXPORT jint JNICALL Java_com_jacob_com_Variant_getVariantErrorRef
(JNIEnv *env, jobject _this) (JNIEnv *env, jobject _this)
{ {
@@ -1076,7 +1125,11 @@ JNIEXPORT jint JNICALL Java_com_jacob_com_Variant_getVariantVariant
VariantClear(v); // whatever was there before VariantClear(v); // whatever was there before
DECIMAL *pd = (DECIMAL *)CoTaskMemAlloc(sizeof(DECIMAL)); DECIMAL *pd = (DECIMAL *)CoTaskMemAlloc(sizeof(DECIMAL));
pd->scale = scale; pd->scale = scale;
pd->sign = signum == 1?0:0x80; if (signum == 1 || signum == 0){
pd->sign = 0;
} else {
pd->sign = 0x80;
}
pd->Hi32 = hi; pd->Hi32 = hi;
pd->Mid32 = mid; pd->Mid32 = mid;
pd->Lo32 = lo; pd->Lo32 = lo;
@@ -1099,7 +1152,11 @@ JNIEXPORT jint JNICALL Java_com_jacob_com_Variant_getVariantVariant
VariantClear(v); // whatever was there before VariantClear(v); // whatever was there before
d = (DECIMAL*)v; d = (DECIMAL*)v;
d->scale = scale; d->scale = scale;
d->sign = signum == 1?0:0x80; if (signum == 1 || signum == 0){
d->sign = 0;
} else {
d->sign = 0x80;
}
d->Hi32 = hi; d->Hi32 = hi;
d->Mid32 = mid; d->Mid32 = mid;
d->Lo32 = lo; d->Lo32 = lo;

View File

@@ -282,6 +282,14 @@ JNIEXPORT jdouble JNICALL Java_com_jacob_com_Variant_getVariantDouble
JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantCurrency JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantCurrency
(JNIEnv *, jobject, jlong); (JNIEnv *, jobject, jlong);
/*
* Class: com_jacob_com_Variant
* Method: putVariantLong
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantLong
(JNIEnv *, jobject, jlong);
/* /*
* Class: com_jacob_com_Variant * Class: com_jacob_com_Variant
* Method: putVariantDispatch * Method: putVariantDispatch
@@ -306,6 +314,13 @@ JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantDouble
JNIEXPORT jlong JNICALL Java_com_jacob_com_Variant_getVariantCurrency JNIEXPORT jlong JNICALL Java_com_jacob_com_Variant_getVariantCurrency
(JNIEnv *, jobject); (JNIEnv *, jobject);
/*
* Class: com_jacob_com_Variant
* Method: getVariantLong
* Signature: ()J
*/
JNIEXPORT jlong JNICALL Java_com_jacob_com_Variant_getVariantLong
(JNIEnv *, jobject);
/* /*
* Class: com_jacob_com_Variant * Class: com_jacob_com_Variant
* Method: putVariantFloatRef * Method: putVariantFloatRef
@@ -322,6 +337,14 @@ JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantFloatRef
JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantCurrencyRef JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantCurrencyRef
(JNIEnv *, jobject, jlong); (JNIEnv *, jobject, jlong);
/*
* Class: com_jacob_com_Variant
* Method: putVariantLongRef
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantLongRef
(JNIEnv *, jobject, jlong);
/* /*
* Class: com_jacob_com_Variant * Class: com_jacob_com_Variant
* Method: putVariantErrorRef * Method: putVariantErrorRef
@@ -386,6 +409,14 @@ JNIEXPORT jfloat JNICALL Java_com_jacob_com_Variant_getVariantFloatRef
JNIEXPORT jlong JNICALL Java_com_jacob_com_Variant_getVariantCurrencyRef JNIEXPORT jlong JNICALL Java_com_jacob_com_Variant_getVariantCurrencyRef
(JNIEnv *, jobject); (JNIEnv *, jobject);
/*
* Class: com_jacob_com_Variant
* Method: getVariantLongRef
* Signature: ()J
*/
JNIEXPORT jlong JNICALL Java_com_jacob_com_Variant_getVariantLongRef
(JNIEnv *, jobject);
/* /*
* Class: com_jacob_com_Variant * Class: com_jacob_com_Variant
* Method: getVariantErrorRef * Method: getVariantErrorRef

View File

@@ -4,15 +4,16 @@ import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.InputStream; import java.io.InputStream;
import com.jacob.com.LibraryLoader;
/** /**
* It is sometimes necessary to run Jacob without being able to install the dll * It is sometimes necessary to run Jacob without being able to install the dll
* on the client machine. This is true in JavaWebStart (JWS) and possibly * on the client machine. This is true in JavaWebStart (JWS) and possibly Applet
* Applet (assuming security allows access to the file system). * (assuming security allows access to the file system). The obvious thing to do
* The obvious thing to do here is to jar up * here is to jar up the Jacob.dll so that it can be downloaded the client along
* the Jacob.dll so that it can be downloaded the client along with the rest * with the rest of the resources. This is simple except that the System.Load()
* of the resources. This is simple except that the System.Load() function * function does not search jar files for DLLs. It searches the classpath. The
* does not search jar files for DLLs. It searches the classpath. * work around to this problem is to write the DLL to a temporary file and then
* The work around to this problem is to write the DLL to a temporary file and then
* explicitly load the DLL calling passing the full path to the temporary file. * explicitly load the DLL calling passing the full path to the temporary file.
* *
* The following code demonstrates this idea. * The following code demonstrates this idea.
@@ -23,43 +24,51 @@ import java.io.InputStream;
public class DLLFromJARClassLoader { public class DLLFromJARClassLoader {
/** /**
* Load the DLL from the classpath rather than from the java path. * Load the DLL from the classpath rather than from the java path. This code
* This code uses this class's class loader to find the dell in one * uses this class's class loader to find the dell in one of the jar files
* of the jar files in this class's class path. It then * in this class's class path. It then writes the file as a temp file and
* writes the file as a temp file and calls Load() on the temp file. * calls Load() on the temp file. The temporary file is marked to be deleted
* The temporary file is marked to be deleted on exit so the dll * on exit so the dll is deleted from the system when the application exits.
* is deleted from the system when the application exits.
* <p> * <p>
* Derived from ample code found in Sun's java forums * Derived from ample code found in Sun's java forums <p.
* <p. *
* @return true if the native library has loaded, false if there was a problem. * @return true if the native library has loaded, false if there was a
* problem.
*/ */
public boolean loadLibrary() public boolean loadLibrary() {
{ try {
try // this assumes that the dll is in the root dir of the signed
{ // jws jar file for this application.
//Finds a stream to the dll. Change path/class if necessary //
InputStream inputStream = getClass().getResource("/jacob.dll").openStream(); // Starting in 1.14M6, the dll is named by platform and architecture
//Change name if necessary // so the best thing to do is to ask the LibraryLoader what name we
File temporaryDll = File.createTempFile("jacob", ".dll"); // expect.
// this code might be different if you customize the name of
// the jacob dll to match some custom naming convention
InputStream inputStream = getClass().getResource(
"/" + LibraryLoader.getPreferredDLLName() + ".dll")
.openStream();
// Put the DLL somewhere we can find it with a name Jacob expects
File temporaryDll = File.createTempFile(LibraryLoader
.getPreferredDLLName(), ".dll");
FileOutputStream outputStream = new FileOutputStream(temporaryDll); FileOutputStream outputStream = new FileOutputStream(temporaryDll);
byte[] array = new byte[8192]; byte[] array = new byte[8192];
for (int i = inputStream.read(array); for (int i = inputStream.read(array); i != -1; i = inputStream
i != -1; .read(array)) {
i = inputStream.read(array)) {
outputStream.write(array, 0, i); outputStream.write(array, 0, i);
} }
outputStream.close(); outputStream.close();
temporaryDll.deleteOnExit(); temporaryDll.deleteOnExit();
System.load(temporaryDll.getPath()); // Ask LibraryLoader to load the dll for us based on the path we
// set
System.setProperty(LibraryLoader.JACOB_DLL_PATH, temporaryDll
.getPath());
LibraryLoader.loadJacobLibrary();
return true; return true;
} } catch (Throwable e) {
catch(Throwable e)
{
e.printStackTrace(); e.printStackTrace();
return false; return false;
} }
} }
} }

View File

@@ -1,24 +1,37 @@
package com.jacob.samples.MathProj; package com.jacob.samples.MathProj;
import com.jacob.activeX.ActiveXComponent; import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.*; import com.jacob.com.Dispatch;
import com.jacob.com.DispatchEvents;
import com.jacob.com.Variant;
/** /**
* This example uses the MathTest sample VB COM DLL under * This example uses the MathTest sample VB COM DLL under the MathProj directory
* the MathProj directory
* <p> * <p>
* May need to run with some command line options (including from inside Eclipse). * May need to run with some command line options (including from inside
* Look in the docs area at the Jacob usage document for command line options. * Eclipse). Look in the docs area at the Jacob usage document for command line
* options.
*/ */
class MathTest { class MathTest {
/**
* standard main program to run the sample
*
* @param args
* command line parameters
*/
public static void main(String[] args) { public static void main(String[] args) {
MathTest me = new MathTest(); MathTest me = new MathTest();
me.runTest(); me.runTest();
} }
/** default constructor */
public MathTest() { public MathTest() {
} }
/**
* not clear why we need a class and run method but that's the way it was
* written
*/
public void runTest() { public void runTest() {
// deprecated // deprecated
// System.runFinalizersOnExit(true); // System.runFinalizersOnExit(true);
@@ -42,11 +55,26 @@ class MathTest {
System.out.println("v.toDispatch=" + v.toDispatch()); System.out.println("v.toDispatch=" + v.toDispatch());
} }
/**
*
* sample class to catch the events
*
*/
public class TestEvents { public class TestEvents {
/**
* catches the DoneAdd event
*
* @param args
*/
public void DoneAdd(Variant[] args) { public void DoneAdd(Variant[] args) {
System.out.println("DoneAdd called in java"); System.out.println("DoneAdd called in java");
} }
/**
* catches the DoneMult event
*
* @param args
*/
public void DoneMult(Variant[] args) { public void DoneMult(Variant[] args) {
System.out.println("DoneMult called in java"); System.out.println("DoneMult called in java");
} }

View File

@@ -19,23 +19,25 @@
*/ */
package com.jacob.samples.access; package com.jacob.samples.access;
import com.jacob.com.*; import com.jacob.activeX.ActiveXComponent;
import com.jacob.activeX.*; import com.jacob.com.ComThread;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
/** /**
* May need to run with some command line options (including from inside Eclipse). * May need to run with some command line options (including from inside
* Look in the docs area at the Jacob usage document for command line options. * Eclipse). Look in the docs area at the Jacob usage document for command line
* options.
* *
*/ */
class Access class Access {
{
/** /**
* the main loop for the test * the main loop for the test
*
* @param args * @param args
* @throws Exception * @throws Exception
*/ */
public static void main(String[] args) throws Exception public static void main(String[] args) throws Exception {
{
ComThread.InitSTA(); ComThread.InitSTA();
// original test used this // original test used this
// ActiveXComponent ax = new ActiveXComponent("DAO.PrivateDBEngine"); // ActiveXComponent ax = new ActiveXComponent("DAO.PrivateDBEngine");
@@ -44,7 +46,8 @@ class Access
// this only works for access files pre-access-2000 // this only works for access files pre-access-2000
// this line doesn't work on my xp box in Eclipse // this line doesn't work on my xp box in Eclipse
// Dispatch db = open(ax, ".\\sample2.mdb"); // Dispatch db = open(ax, ".\\sample2.mdb");
// this works when running in eclipse because the test cases run pwd project root // this works when running in eclipse because the test cases run pwd
// project root
Dispatch db = open(ax, "samples/com/jacob/samples/access/sample2.mdb"); Dispatch db = open(ax, "samples/com/jacob/samples/access/sample2.mdb");
String sql = "select * from MainTable"; String sql = "select * from MainTable";
// make a temporary querydef // make a temporary querydef
@@ -61,12 +64,12 @@ class Access
/** /**
* Open a database * Open a database
*
* @param ax * @param ax
* @param fileName * @param fileName
* @return dispatch object that was opened * @return dispatch object that was opened
*/ */
public static Dispatch open(ActiveXComponent ax, String fileName) public static Dispatch open(ActiveXComponent ax, String fileName) {
{
Variant f = new Variant(false); Variant f = new Variant(false);
// open the file in read-only mode // open the file in read-only mode
Variant[] args = new Variant[] { new Variant(fileName), f, f }; Variant[] args = new Variant[] { new Variant(fileName), f, f };
@@ -76,20 +79,21 @@ class Access
/** /**
* Close a database * Close a database
* @param openDB db to be closed *
* @param openDB
* db to be closed
*/ */
public static void close(Dispatch openDB) public static void close(Dispatch openDB) {
{
Dispatch.call(openDB, "Close"); Dispatch.call(openDB, "Close");
} }
/** /**
* Extract the values from the recordset * Extract the values from the recordset
*
* @param recset * @param recset
* @return Variant that is the returned values * @return Variant that is the returned values
*/ */
public static Variant getValues(Dispatch recset) public static Variant getValues(Dispatch recset) {
{
Dispatch.callSub(recset, "moveFirst"); Dispatch.callSub(recset, "moveFirst");
Variant vi = new Variant(4096); Variant vi = new Variant(4096);
Variant v = Dispatch.call(recset, "GetRows", vi); Variant v = Dispatch.call(recset, "GetRows", vi);
@@ -98,17 +102,16 @@ class Access
/** /**
* should return ?? for the passed in ?? * should return ?? for the passed in ??
*
* @param qd * @param qd
* @return Variant results of query? * @return Variant results of query?
*/ */
public static Variant getByQueryDef(Dispatch qd) public static Variant getByQueryDef(Dispatch qd) {
{
// get a reference to the recordset // get a reference to the recordset
Dispatch recset = Dispatch.call(qd, "OpenRecordset").toDispatch(); Dispatch recset = Dispatch.call(qd, "OpenRecordset").toDispatch();
// get the values as a safe array // get the values as a safe array
String[] cols = getColumns(recset); String[] cols = getColumns(recset);
for(int i=0;i<cols.length;i++) for (int i = 0; i < cols.length; i++) {
{
System.out.print(cols[i] + " "); System.out.print(cols[i] + " ");
} }
System.out.println(""); System.out.println("");
@@ -118,11 +121,11 @@ class Access
/** /**
* gets the columns form the rec set * gets the columns form the rec set
*
* @param recset * @param recset
* @return list of column names * @return list of column names
*/ */
public static String[] getColumns(Dispatch recset) public static String[] getColumns(Dispatch recset) {
{
Dispatch flds = Dispatch.get(recset, "Fields").toDispatch(); Dispatch flds = Dispatch.get(recset, "Fields").toDispatch();
int n_flds = Dispatch.get(flds, "Count").getInt(); int n_flds = Dispatch.get(flds, "Count").getInt();
String[] s = new String[n_flds]; String[] s = new String[n_flds];
@@ -131,8 +134,8 @@ class Access
vi.putInt(i); vi.putInt(i);
// must use the invoke method because this is a method call // must use the invoke method because this is a method call
// that wants to have a Dispatch.Get flag... // that wants to have a Dispatch.Get flag...
Dispatch fld = Dispatch.invoke(recset, "Fields", Dispatch fld = Dispatch.invoke(recset, "Fields", Dispatch.Get,
Dispatch.Get, new Object[] {vi}, new int[1]).toDispatch(); new Object[] { vi }, new int[1]).toDispatch();
Variant name = Dispatch.get(fld, "Name"); Variant name = Dispatch.get(fld, "Name");
s[i] = name.toString(); s[i] = name.toString();
} }

View File

@@ -1,120 +1,207 @@
package com.jacob.samples.ado; package com.jacob.samples.ado;
import com.jacob.com.*; import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
public class Command extends Dispatch /**
{ * Custom dispatch object to make it easy for us to provide application specific
public Command() * API.
{ *
*/
public class Command extends Dispatch {
/**
* standard constructor
*/
public Command() {
super("ADODB.Command"); super("ADODB.Command");
} }
/** /**
* This constructor is used instead of a case operation to * This constructor is used instead of a case operation to turn a Dispatch
* turn a Dispatch object into a wider object - it must exist * object into a wider object - it must exist in every wrapper class whose
* in every wrapper class whose instances may be returned from * instances may be returned from method calls wrapped in VT_DISPATCH
* method calls wrapped in VT_DISPATCH Variants. * Variants.
*
* @param dispatchTarget * @param dispatchTarget
*/ */
public Command(Dispatch dispatchTarget) public Command(Dispatch dispatchTarget) {
{
super(dispatchTarget); super(dispatchTarget);
} }
public Variant getProperties() /**
{ * runs the "Properties" command
*
* @return the properties
*/
public Variant getProperties() {
return Dispatch.get(this, "Properties"); return Dispatch.get(this, "Properties");
} }
public Connection getActiveConnection() /**
{ * runs the "ActiveConnection" command
return new Connection(Dispatch.get(this, "ActiveConnection").toDispatch()); *
* @return a Connection object
*/
public Connection getActiveConnection() {
return new Connection(Dispatch.get(this, "ActiveConnection")
.toDispatch());
} }
public void setActiveConnection(Connection ppvObject) /**
{ * Sets the "ActiveConnection" object
*
* @param ppvObject
* the new connection
*/
public void setActiveConnection(Connection ppvObject) {
Dispatch.put(this, "ActiveConnection", ppvObject); Dispatch.put(this, "ActiveConnection", ppvObject);
} }
public String getCommandText() /**
{ *
* @return the results from "CommandText"
*/
public String getCommandText() {
return Dispatch.get(this, "CommandText").toString(); return Dispatch.get(this, "CommandText").toString();
} }
public void setCommandText(String pbstr) /**
{ *
* @param pbstr
* the new "CommandText"
*/
public void setCommandText(String pbstr) {
Dispatch.put(this, "CommandText", pbstr); Dispatch.put(this, "CommandText", pbstr);
} }
public int getCommandTimeout() /**
{ *
* @return the results of "CommandTimeout"
*/
public int getCommandTimeout() {
return Dispatch.get(this, "CommandTimeout").getInt(); return Dispatch.get(this, "CommandTimeout").getInt();
} }
public void setCommandTimeout(int plTimeout) /**
{ *
* @param plTimeout
* the new "CommandTimeout"
*/
public void setCommandTimeout(int plTimeout) {
Dispatch.put(this, "CommandTimeout", new Variant(plTimeout)); Dispatch.put(this, "CommandTimeout", new Variant(plTimeout));
} }
public boolean getPrepared() /**
{ *
* @return results from "Prepared"
*/
public boolean getPrepared() {
return Dispatch.get(this, "Prepared").getBoolean(); return Dispatch.get(this, "Prepared").getBoolean();
} }
public void setPrepared(boolean pfPrepared) /**
{ *
* @param pfPrepared
* the new value for "Prepared"
*/
public void setPrepared(boolean pfPrepared) {
Dispatch.put(this, "Prepared", new Variant(pfPrepared)); Dispatch.put(this, "Prepared", new Variant(pfPrepared));
} }
public Recordset Execute(Variant RecordsAffected, Variant Parameters, int Options) /**
{ * "Execute"s a command
return (Recordset)Dispatch.call(this, "Execute", RecordsAffected, Parameters, new Variant(Options)).toDispatch(); *
* @param RecordsAffected
* @param Parameters
* @param Options
* @return
*/
public Recordset Execute(Variant RecordsAffected, Variant Parameters,
int Options) {
return (Recordset) Dispatch.call(this, "Execute", RecordsAffected,
Parameters, new Variant(Options)).toDispatch();
} }
public Recordset Execute() /**
{ * "Execute"s a command
*
* @return
*/
public Recordset Execute() {
Variant dummy = new Variant(); Variant dummy = new Variant();
return new Recordset(Dispatch.call(this, "Execute", dummy).toDispatch()); return new Recordset(Dispatch.call(this, "Execute", dummy).toDispatch());
} }
public Variant CreateParameter(String Name, int Type, int Direction, int Size, Variant Value) /**
{ * creates a parameter
return Dispatch.call(this, "CreateParameter", Name, new Variant(Type), new Variant(Direction), new Variant(Size), Value); *
* @param Name
* @param Type
* @param Direction
* @param Size
* @param Value
* @return
*/
public Variant CreateParameter(String Name, int Type, int Direction,
int Size, Variant Value) {
return Dispatch.call(this, "CreateParameter", Name, new Variant(Type),
new Variant(Direction), new Variant(Size), Value);
} }
// need to wrap Parameters // need to wrap Parameters
public Variant getParameters() /**
{ * @return "Parameters"
*/
public Variant getParameters() {
return Dispatch.get(this, "Parameters"); return Dispatch.get(this, "Parameters");
} }
public void setCommandType(int plCmdType) /**
{ *
* @param plCmdType
* new "CommandType"
*/
public void setCommandType(int plCmdType) {
Dispatch.put(this, "CommandType", new Variant(plCmdType)); Dispatch.put(this, "CommandType", new Variant(plCmdType));
} }
public int getCommandType() /**
{ *
* @return current "CommandType"
*/
public int getCommandType() {
return Dispatch.get(this, "CommandType").getInt(); return Dispatch.get(this, "CommandType").getInt();
} }
public String getName() /**
{ *
* @return "Name"
*/
public String getName() {
return Dispatch.get(this, "Name").toString(); return Dispatch.get(this, "Name").toString();
} }
public void setName(String pbstrName) /**
{ *
* @param pbstrName
* new "Name"
*/
public void setName(String pbstrName) {
Dispatch.put(this, "Name", pbstrName); Dispatch.put(this, "Name", pbstrName);
} }
public int getState() /**
{ *
* @return curent "State"
*/
public int getState() {
return Dispatch.get(this, "State").getInt(); return Dispatch.get(this, "State").getInt();
} }
public void Cancel() /**
{ * cancel whatever it is we're doing
*/
public void Cancel() {
Dispatch.call(this, "Cancel"); Dispatch.call(this, "Cancel");
} }
} }

View File

@@ -2,8 +2,7 @@ package com.jacob.samples.ado;
// Enum: CommandTypeEnum // Enum: CommandTypeEnum
public interface CommandTypeEnum public interface CommandTypeEnum {
{
public static final int adCmdUnspecified = -1; public static final int adCmdUnspecified = -1;
public static final int adCmdUnknown = 8; public static final int adCmdUnknown = 8;
public static final int adCmdText = 1; public static final int adCmdText = 1;

View File

@@ -1,179 +1,151 @@
package com.jacob.samples.ado; package com.jacob.samples.ado;
import com.jacob.com.*; import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
public class Connection extends Dispatch public class Connection extends Dispatch {
{ public Connection() {
public Connection()
{
super("ADODB.Connection"); super("ADODB.Connection");
} }
/** /**
* This constructor is used instead of a case operation to * This constructor is used instead of a case operation to turn a Dispatch
* turn a Dispatch object into a wider object - it must exist * object into a wider object - it must exist in every wrapper class whose
* in every wrapper class whose instances may be returned from * instances may be returned from method calls wrapped in VT_DISPATCH
* method calls wrapped in VT_DISPATCH Variants. * Variants.
*/ */
public Connection(Dispatch d) public Connection(Dispatch d) {
{
super(d); super(d);
} }
// need to wrap Properties // need to wrap Properties
public Variant getProperties() public Variant getProperties() {
{
return Dispatch.get(this, "Properties"); return Dispatch.get(this, "Properties");
} }
public String getConnectionString() public String getConnectionString() {
{
return Dispatch.get(this, "ConnectionString").toString(); return Dispatch.get(this, "ConnectionString").toString();
} }
public void setConnectionString(String pbstr) public void setConnectionString(String pbstr) {
{
Dispatch.put(this, "ConnectionString", pbstr); Dispatch.put(this, "ConnectionString", pbstr);
} }
public int getCommandTimeout() public int getCommandTimeout() {
{
return Dispatch.get(this, "CommandTimeout").getInt(); return Dispatch.get(this, "CommandTimeout").getInt();
} }
public void setCommandTimeout(int plTimeout) public void setCommandTimeout(int plTimeout) {
{
Dispatch.put(this, "CommandTimeout", new Variant(plTimeout)); Dispatch.put(this, "CommandTimeout", new Variant(plTimeout));
} }
public int getConnectionTimeout() public int getConnectionTimeout() {
{
return Dispatch.get(this, "ConnectionTimeout").getInt(); return Dispatch.get(this, "ConnectionTimeout").getInt();
} }
public void setConnectionTimeout(int plTimeout) public void setConnectionTimeout(int plTimeout) {
{
Dispatch.put(this, "ConnectionTimeout", new Variant(plTimeout)); Dispatch.put(this, "ConnectionTimeout", new Variant(plTimeout));
} }
public String getVersion() public String getVersion() {
{
return Dispatch.get(this, "Version").toString(); return Dispatch.get(this, "Version").toString();
} }
public void Close() public void Close() {
{
Dispatch.call(this, "Close"); Dispatch.call(this, "Close");
} }
// how to deal with RecordsAffected being output? // how to deal with RecordsAffected being output?
public Variant Execute(String CommandText, Variant RecordsAffected, int Options) public Variant Execute(String CommandText, Variant RecordsAffected,
{ int Options) {
return Dispatch.call(this, CommandText, RecordsAffected, new Variant(Options)); return Dispatch.call(this, CommandText, RecordsAffected, new Variant(
Options));
} }
public int BeginTrans() public int BeginTrans() {
{
return Dispatch.call(this, "BeginTrans").getInt(); return Dispatch.call(this, "BeginTrans").getInt();
} }
public void CommitTrans() public void CommitTrans() {
{
Dispatch.call(this, "CommitTrans"); Dispatch.call(this, "CommitTrans");
} }
public void RollbackTrans() public void RollbackTrans() {
{
Dispatch.call(this, "RollbackTrans"); Dispatch.call(this, "RollbackTrans");
} }
public void Open(String ConnectionString, String UserID, String Password, int Options) public void Open(String ConnectionString, String UserID, String Password,
{ int Options) {
Dispatch.call(this, "Open", ConnectionString, UserID, Password, new Variant(Options)); Dispatch.call(this, "Open", ConnectionString, UserID, Password,
new Variant(Options));
} }
public void Open() public void Open() {
{
Dispatch.call(this, "Open"); Dispatch.call(this, "Open");
} }
public Variant getErrors() public Variant getErrors() {
{
return Dispatch.get(this, "Errors"); return Dispatch.get(this, "Errors");
} }
public String getDefaultDatabase() public String getDefaultDatabase() {
{
return Dispatch.get(this, "DefaultDatabase").toString(); return Dispatch.get(this, "DefaultDatabase").toString();
} }
public void setDefaultDatabase(String pbstr) public void setDefaultDatabase(String pbstr) {
{
Dispatch.put(this, "DefaultDatabase", pbstr); Dispatch.put(this, "DefaultDatabase", pbstr);
} }
public int getIsolationLevel() public int getIsolationLevel() {
{
return Dispatch.get(this, "IsolationLevel").getInt(); return Dispatch.get(this, "IsolationLevel").getInt();
} }
public void setIsolationLevel(int Level) public void setIsolationLevel(int Level) {
{
Dispatch.put(this, "IsolationLevel", new Variant(Level)); Dispatch.put(this, "IsolationLevel", new Variant(Level));
} }
public int getAttributes() public int getAttributes() {
{
return Dispatch.get(this, "Attributes").getInt(); return Dispatch.get(this, "Attributes").getInt();
} }
public void setAttributes(int plAttr) public void setAttributes(int plAttr) {
{
Dispatch.put(this, "Attributes", new Variant(plAttr)); Dispatch.put(this, "Attributes", new Variant(plAttr));
} }
public int getCursorLocation() public int getCursorLocation() {
{
return Dispatch.get(this, "CursorLocation").getInt(); return Dispatch.get(this, "CursorLocation").getInt();
} }
public void setCursorLocation(int plCursorLoc) public void setCursorLocation(int plCursorLoc) {
{
Dispatch.put(this, "CursorLocation", new Variant(plCursorLoc)); Dispatch.put(this, "CursorLocation", new Variant(plCursorLoc));
} }
public int getMode() public int getMode() {
{
return Dispatch.get(this, "Mode").getInt(); return Dispatch.get(this, "Mode").getInt();
} }
public void setMode(int plMode) public void setMode(int plMode) {
{
Dispatch.put(this, "Mode", new Variant(plMode)); Dispatch.put(this, "Mode", new Variant(plMode));
} }
public String getProvider() public String getProvider() {
{
return Dispatch.get(this, "Provider").toString(); return Dispatch.get(this, "Provider").toString();
} }
public void setProvider(String pbstr) public void setProvider(String pbstr) {
{
Dispatch.put(this, "Provider", pbstr); Dispatch.put(this, "Provider", pbstr);
} }
public int getState() public int getState() {
{
return Dispatch.get(this, "State").getInt(); return Dispatch.get(this, "State").getInt();
} }
public Variant OpenSchema(int Schema, Variant Restrictions, Variant SchemaID) public Variant OpenSchema(int Schema, Variant Restrictions, Variant SchemaID) {
{ return Dispatch.call(this, "OpenSchema", new Variant(Schema),
return Dispatch.call(this, "OpenSchema", new Variant(Schema), Restrictions, SchemaID); Restrictions, SchemaID);
} }
public void Cancel() public void Cancel() {
{
Dispatch.call(this, "Cancel"); Dispatch.call(this, "Cancel");
} }
} }

View File

@@ -1,121 +1,100 @@
package com.jacob.samples.ado; package com.jacob.samples.ado;
import com.jacob.com.*;
public class Field extends Dispatch import com.jacob.com.Dispatch;
{ import com.jacob.com.Variant;
public class Field extends Dispatch {
/** /**
* This constructor is used instead of a case operation to * This constructor is used instead of a case operation to turn a Dispatch
* turn a Dispatch object into a wider object - it must exist * object into a wider object - it must exist in every wrapper class whose
* in every wrapper class whose instances may be returned from * instances may be returned from method calls wrapped in VT_DISPATCH
* method calls wrapped in VT_DISPATCH Variants. * Variants.
*/ */
public Field(Dispatch d) public Field(Dispatch d) {
{
super(d); super(d);
} }
public Variant getProperties() public Variant getProperties() {
{
return Dispatch.get(this, "Properties"); return Dispatch.get(this, "Properties");
} }
public int getActualSize() public int getActualSize() {
{
return Dispatch.get(this, "ActualSize").getInt(); return Dispatch.get(this, "ActualSize").getInt();
} }
public int getAttributes() public int getAttributes() {
{
return Dispatch.get(this, "Attributes").getInt(); return Dispatch.get(this, "Attributes").getInt();
} }
public int getDefinedSize() public int getDefinedSize() {
{
return Dispatch.get(this, "DefinedSize").getInt(); return Dispatch.get(this, "DefinedSize").getInt();
} }
public String getName() public String getName() {
{
return Dispatch.get(this, "Name").toString(); return Dispatch.get(this, "Name").toString();
} }
public int getType() public int getType() {
{
return Dispatch.get(this, "Type").getInt(); return Dispatch.get(this, "Type").getInt();
} }
public Variant getValue() public Variant getValue() {
{
return Dispatch.get(this, "Value"); return Dispatch.get(this, "Value");
} }
public void setValue(Variant pvar) public void setValue(Variant pvar) {
{
Dispatch.put(this, "Value", pvar); Dispatch.put(this, "Value", pvar);
} }
public byte getPrecision() public byte getPrecision() {
{
return Dispatch.get(this, "Precision").getByte(); return Dispatch.get(this, "Precision").getByte();
} }
public byte getNumericScale() public byte getNumericScale() {
{
return Dispatch.get(this, "NumericScale").getByte(); return Dispatch.get(this, "NumericScale").getByte();
} }
public void AppendChunk(Variant Data) public void AppendChunk(Variant Data) {
{
Dispatch.call(this, "AppendChunk", Data); Dispatch.call(this, "AppendChunk", Data);
} }
public Variant GetChunk(int Length) public Variant GetChunk(int Length) {
{
return Dispatch.call(this, "GetChunk", new Variant(Length)); return Dispatch.call(this, "GetChunk", new Variant(Length));
} }
public Variant getOriginalValue() public Variant getOriginalValue() {
{
return Dispatch.get(this, "OriginalValue"); return Dispatch.get(this, "OriginalValue");
} }
public Variant getUnderlyingValue() public Variant getUnderlyingValue() {
{
return Dispatch.get(this, "UnderlyingValue"); return Dispatch.get(this, "UnderlyingValue");
} }
public Variant getDataFormat() public Variant getDataFormat() {
{
return Dispatch.get(this, "DataFormat"); return Dispatch.get(this, "DataFormat");
} }
public void setDataFormat(Variant ppiDF) public void setDataFormat(Variant ppiDF) {
{
Dispatch.put(this, "DataFormat", ppiDF); Dispatch.put(this, "DataFormat", ppiDF);
} }
public void setPrecision(byte pb) public void setPrecision(byte pb) {
{
Dispatch.put(this, "Precision", new Variant(pb)); Dispatch.put(this, "Precision", new Variant(pb));
} }
public void setNumericScale(byte pb) public void setNumericScale(byte pb) {
{
Dispatch.put(this, "NumericScale", new Variant(pb)); Dispatch.put(this, "NumericScale", new Variant(pb));
} }
public void setType(int pDataType) public void setType(int pDataType) {
{
Dispatch.put(this, "Type", new Variant(pDataType)); Dispatch.put(this, "Type", new Variant(pDataType));
} }
public void setDefinedSize(int pl) public void setDefinedSize(int pl) {
{
Dispatch.put(this, "DefinedSize", new Variant(pl)); Dispatch.put(this, "DefinedSize", new Variant(pl));
} }
public void setAttributes(int pl) public void setAttributes(int pl) {
{
Dispatch.put(this, "Attributes", new Variant(pl)); Dispatch.put(this, "Attributes", new Variant(pl));
} }

View File

@@ -1,47 +1,42 @@
package com.jacob.samples.ado; package com.jacob.samples.ado;
import com.jacob.com.*;
public class Fields extends Dispatch import com.jacob.com.Dispatch;
{ import com.jacob.com.Variant;
public class Fields extends Dispatch {
/** /**
* This constructor is used instead of a case operation to * This constructor is used instead of a case operation to turn a Dispatch
* turn a Dispatch object into a wider object - it must exist * object into a wider object - it must exist in every wrapper class whose
* in every wrapper class whose instances may be returned from * instances may be returned from method calls wrapped in VT_DISPATCH
* method calls wrapped in VT_DISPATCH Variants. * Variants.
*/ */
public Fields(Dispatch d) public Fields(Dispatch d) {
{
super(d); super(d);
} }
public int getCount() public int getCount() {
{
return Dispatch.get(this, "Count").getInt(); return Dispatch.get(this, "Count").getInt();
} }
public Variant _NewEnum() public Variant _NewEnum() {
{
return Dispatch.call(this, "_NewEnum"); return Dispatch.call(this, "_NewEnum");
} }
public void Refresh() public void Refresh() {
{
Dispatch.call(this, "Refresh"); Dispatch.call(this, "Refresh");
} }
public Field getItem(int Index) public Field getItem(int Index) {
{ return new Field(Dispatch.call(this, "Item", new Variant(Index))
return new Field(Dispatch.call(this, "Item", new Variant(Index)).toDispatch()); .toDispatch());
} }
public void Append(String Name, int Type, int DefinedSize, int Attrib) public void Append(String Name, int Type, int DefinedSize, int Attrib) {
{ Dispatch.call(this, "Append", Name, new Variant(Type), new Variant(
Dispatch.call(this, "Append", Name, new Variant(Type), DefinedSize), new Variant(Attrib));
new Variant(DefinedSize), new Variant(Attrib));
} }
public void Delete(Variant Index) public void Delete(Variant Index) {
{
Dispatch.call(this, "Delete", Index); Dispatch.call(this, "Delete", Index);
} }

View File

@@ -1,409 +1,342 @@
package com.jacob.samples.ado; package com.jacob.samples.ado;
import com.jacob.com.*;
public class Recordset extends Dispatch import com.jacob.com.Dispatch;
{ import com.jacob.com.Variant;
public Recordset()
{ public class Recordset extends Dispatch {
public Recordset() {
super("ADODB.Recordset"); super("ADODB.Recordset");
} }
/** /**
* This constructor is used instead of a case operation to * This constructor is used instead of a case operation to turn a Dispatch
* turn a Dispatch object into a wider object - it must exist * object into a wider object - it must exist in every wrapper class whose
* in every wrapper class whose instances may be returned from * instances may be returned from method calls wrapped in VT_DISPATCH
* method calls wrapped in VT_DISPATCH Variants. * Variants.
*/ */
public Recordset(Dispatch d) public Recordset(Dispatch d) {
{
super(d); super(d);
} }
public Variant getProperties() public Variant getProperties() {
{
return Dispatch.get(this, "Properties"); return Dispatch.get(this, "Properties");
} }
public int getAbsolutePosition() public int getAbsolutePosition() {
{
return Dispatch.get(this, "AbsolutePosition").getInt(); return Dispatch.get(this, "AbsolutePosition").getInt();
} }
public void setAbsolutePosition(int pl) public void setAbsolutePosition(int pl) {
{
Dispatch.put(this, "AbsolutePosition", new Variant(pl)); Dispatch.put(this, "AbsolutePosition", new Variant(pl));
} }
public Connection getActiveConnection() public Connection getActiveConnection() {
{ return new Connection(Dispatch.get(this, "ActiveConnection")
return new Connection(Dispatch.get(this, "ActiveConnection").toDispatch()); .toDispatch());
} }
public void setActiveConnection(Connection ppvObject) public void setActiveConnection(Connection ppvObject) {
{
Dispatch.put(this, "ActiveConnection", ppvObject); Dispatch.put(this, "ActiveConnection", ppvObject);
} }
public void setActiveConnection(Variant ppvObject) public void setActiveConnection(Variant ppvObject) {
{
Dispatch.put(this, "ActiveConnection", ppvObject); Dispatch.put(this, "ActiveConnection", ppvObject);
} }
public boolean getBOF() public boolean getBOF() {
{
return Dispatch.get(this, "BOF").getBoolean(); return Dispatch.get(this, "BOF").getBoolean();
} }
public Variant getBookmark() public Variant getBookmark() {
{
return Dispatch.get(this, "Bookmark"); return Dispatch.get(this, "Bookmark");
} }
public void setBookmark(Variant pvBookmark) public void setBookmark(Variant pvBookmark) {
{
Dispatch.put(this, "Bookmark", pvBookmark); Dispatch.put(this, "Bookmark", pvBookmark);
} }
public int getCacheSize() public int getCacheSize() {
{
return Dispatch.get(this, "CacheSize").getInt(); return Dispatch.get(this, "CacheSize").getInt();
} }
public void setCacheSize(int pl) public void setCacheSize(int pl) {
{
Dispatch.put(this, "CacheSize", new Variant(pl)); Dispatch.put(this, "CacheSize", new Variant(pl));
} }
public int getCursorType() public int getCursorType() {
{
return Dispatch.get(this, "CursorType").getInt(); return Dispatch.get(this, "CursorType").getInt();
} }
public void setCursorType(int pl) public void setCursorType(int pl) {
{
Dispatch.put(this, "CursorType", new Variant(pl)); Dispatch.put(this, "CursorType", new Variant(pl));
} }
public boolean getEOF() public boolean getEOF() {
{
return Dispatch.get(this, "EOF").getBoolean(); return Dispatch.get(this, "EOF").getBoolean();
} }
public Fields getFields() public Fields getFields() {
{
return new Fields(Dispatch.get(this, "Fields").toDispatch()); return new Fields(Dispatch.get(this, "Fields").toDispatch());
} }
public int getLockType() public int getLockType() {
{
return Dispatch.get(this, "LockType").getInt(); return Dispatch.get(this, "LockType").getInt();
} }
public void setLockType(int plLockType) public void setLockType(int plLockType) {
{
Dispatch.put(this, "LockType", new Variant(plLockType)); Dispatch.put(this, "LockType", new Variant(plLockType));
} }
public int getMaxRecords() public int getMaxRecords() {
{
return Dispatch.get(this, "MaxRecords").getInt(); return Dispatch.get(this, "MaxRecords").getInt();
} }
public void setMaxRecords(int pl) public void setMaxRecords(int pl) {
{
Dispatch.put(this, "MaxRecords", new Variant(pl)); Dispatch.put(this, "MaxRecords", new Variant(pl));
} }
public int getRecordCount() public int getRecordCount() {
{
return Dispatch.get(this, "RecordCount").getInt(); return Dispatch.get(this, "RecordCount").getInt();
} }
public void setSource(Object pvSource) public void setSource(Object pvSource) {
{
Dispatch.put(this, "Source", pvSource); Dispatch.put(this, "Source", pvSource);
} }
public void setSource(String pvSource) public void setSource(String pvSource) {
{
Dispatch.put(this, "Source", pvSource); Dispatch.put(this, "Source", pvSource);
} }
public Variant getSource() public Variant getSource() {
{
return Dispatch.get(this, "Source"); return Dispatch.get(this, "Source");
} }
public void AddNew(Variant FieldList, Variant Values) public void AddNew(Variant FieldList, Variant Values) {
{
Dispatch.call(this, "AddNew", FieldList, Values); Dispatch.call(this, "AddNew", FieldList, Values);
} }
public void CancelUpdate() public void CancelUpdate() {
{
Dispatch.call(this, "CancelUpdate"); Dispatch.call(this, "CancelUpdate");
} }
public void Close() public void Close() {
{
Dispatch.call(this, "Close"); Dispatch.call(this, "Close");
} }
public void Delete(int AffectRecords) public void Delete(int AffectRecords) {
{
Dispatch.call(this, "Delete", new Variant(AffectRecords)); Dispatch.call(this, "Delete", new Variant(AffectRecords));
} }
public Variant GetRows(int Rows, Variant Start, Variant Fields) public Variant GetRows(int Rows, Variant Start, Variant Fields) {
{
return Dispatch.call(this, "GetRows", new Variant(Rows), Start, Fields); return Dispatch.call(this, "GetRows", new Variant(Rows), Start, Fields);
} }
// get all rows // get all rows
public Variant GetRows() public Variant GetRows() {
{
return Dispatch.call(this, "GetRows"); return Dispatch.call(this, "GetRows");
} }
public void Move(int NumRecords, Variant Start) public void Move(int NumRecords, Variant Start) {
{
Dispatch.call(this, "Move", new Variant(NumRecords), Start); Dispatch.call(this, "Move", new Variant(NumRecords), Start);
} }
public void MoveNext() public void MoveNext() {
{
Dispatch.call(this, "MoveNext"); Dispatch.call(this, "MoveNext");
} }
public void MovePrevious() public void MovePrevious() {
{
Dispatch.call(this, "MovePrevious"); Dispatch.call(this, "MovePrevious");
} }
public void MoveFirst() public void MoveFirst() {
{
Dispatch.call(this, "MoveFirst"); Dispatch.call(this, "MoveFirst");
} }
public void MoveLast() public void MoveLast() {
{
Dispatch.call(this, "MoveLast"); Dispatch.call(this, "MoveLast");
} }
public void Open(Variant Source, Variant ActiveConnection, int CursorType, int LockType, int Options) public void Open(Variant Source, Variant ActiveConnection, int CursorType,
{ int LockType, int Options) {
Dispatch.call(this, "Open", Source, ActiveConnection, new Variant(CursorType), new Variant(LockType), new Variant(Options)); Dispatch.call(this, "Open", Source, ActiveConnection, new Variant(
CursorType), new Variant(LockType), new Variant(Options));
} }
public void Open(Variant Source, Variant ActiveConnection) public void Open(Variant Source, Variant ActiveConnection) {
{
Dispatch.call(this, "Open", Source, ActiveConnection); Dispatch.call(this, "Open", Source, ActiveConnection);
} }
public void Requery(int Options) public void Requery(int Options) {
{
Dispatch.call(this, "Requery", new Variant(Options)); Dispatch.call(this, "Requery", new Variant(Options));
} }
public void Update(Variant Fields, Variant Values) public void Update(Variant Fields, Variant Values) {
{
Dispatch.call(this, "Update", Fields, Values); Dispatch.call(this, "Update", Fields, Values);
} }
public int getAbsolutePage() public int getAbsolutePage() {
{
return Dispatch.get(this, "AbsolutePage").getInt(); return Dispatch.get(this, "AbsolutePage").getInt();
} }
public void setAbsolutePage(int pl) public void setAbsolutePage(int pl) {
{
Dispatch.put(this, "AbsolutePage", new Variant(pl)); Dispatch.put(this, "AbsolutePage", new Variant(pl));
} }
public int getEditMode() public int getEditMode() {
{
return Dispatch.get(this, "EditMode").getInt(); return Dispatch.get(this, "EditMode").getInt();
} }
public Variant getFilter() public Variant getFilter() {
{
return Dispatch.get(this, "Filter"); return Dispatch.get(this, "Filter");
} }
public void setFilter(Variant Criteria) public void setFilter(Variant Criteria) {
{
Dispatch.put(this, "Filter", Criteria); Dispatch.put(this, "Filter", Criteria);
} }
public int getPageCount() public int getPageCount() {
{
return Dispatch.get(this, "PageCount").getInt(); return Dispatch.get(this, "PageCount").getInt();
} }
public int getPageSize() public int getPageSize() {
{
return Dispatch.get(this, "PageSize").getInt(); return Dispatch.get(this, "PageSize").getInt();
} }
public void setPageSize(int pl) public void setPageSize(int pl) {
{
Dispatch.put(this, "PageSize", new Variant(pl)); Dispatch.put(this, "PageSize", new Variant(pl));
} }
public String getSort() public String getSort() {
{
return Dispatch.get(this, "Sort").toString(); return Dispatch.get(this, "Sort").toString();
} }
public void setSort(String Criteria) public void setSort(String Criteria) {
{
Dispatch.put(this, "Sort", Criteria); Dispatch.put(this, "Sort", Criteria);
} }
public int getStatus() public int getStatus() {
{
return Dispatch.get(this, "Status").getInt(); return Dispatch.get(this, "Status").getInt();
} }
public int getState() public int getState() {
{
return Dispatch.get(this, "State").getInt(); return Dispatch.get(this, "State").getInt();
} }
public void UpdateBatch(int AffectRecords) public void UpdateBatch(int AffectRecords) {
{
Dispatch.call(this, "UpdateBatch", new Variant(AffectRecords)); Dispatch.call(this, "UpdateBatch", new Variant(AffectRecords));
} }
public void CancelBatch(int AffectRecords) public void CancelBatch(int AffectRecords) {
{
Dispatch.call(this, "CancelBatch", new Variant(AffectRecords)); Dispatch.call(this, "CancelBatch", new Variant(AffectRecords));
} }
public int getCursorLocation() public int getCursorLocation() {
{
return Dispatch.get(this, "CursorLocation").getInt(); return Dispatch.get(this, "CursorLocation").getInt();
} }
public void setCursorLocation(int pl) public void setCursorLocation(int pl) {
{
Dispatch.put(this, "CursorLocation", new Variant(pl)); Dispatch.put(this, "CursorLocation", new Variant(pl));
} }
public Recordset NextRecordset(Variant RecordsAffected) public Recordset NextRecordset(Variant RecordsAffected) {
{ return new Recordset(Dispatch.call(this, "NextRecordset",
return new Recordset(Dispatch.call(this, "NextRecordset", RecordsAffected).toDispatch()); RecordsAffected).toDispatch());
} }
public boolean Supports(int CursorOptions) public boolean Supports(int CursorOptions) {
{ return Dispatch.call(this, "Supports", new Variant(CursorOptions))
return Dispatch.call(this, "Supports", new Variant(CursorOptions)).getBoolean(); .getBoolean();
} }
public Variant getCollect(Variant Index) public Variant getCollect(Variant Index) {
{
return Dispatch.get(this, "Collect"); return Dispatch.get(this, "Collect");
} }
public void setCollect(Variant Index, Variant pvar) public void setCollect(Variant Index, Variant pvar) {
{
Dispatch.call(this, "Collect", Index, pvar); Dispatch.call(this, "Collect", Index, pvar);
} }
public int getMarshalOptions() public int getMarshalOptions() {
{
return Dispatch.get(this, "MarshalOptions").getInt(); return Dispatch.get(this, "MarshalOptions").getInt();
} }
public void setMarshalOptions(int pl) public void setMarshalOptions(int pl) {
{
Dispatch.put(this, "MarshalOptions", new Variant(pl)); Dispatch.put(this, "MarshalOptions", new Variant(pl));
} }
public void Find(String Criteria, int SkipRecords, int SearchDirection, Variant Start) public void Find(String Criteria, int SkipRecords, int SearchDirection,
{ Variant Start) {
Dispatch.call(this, "Find", Criteria, new Variant(SkipRecords), new Variant(SearchDirection), Start); Dispatch.call(this, "Find", Criteria, new Variant(SkipRecords),
new Variant(SearchDirection), Start);
} }
public void Cancel() public void Cancel() {
{
Dispatch.call(this, "Cancel"); Dispatch.call(this, "Cancel");
} }
public Variant getDataSource() public Variant getDataSource() {
{
return Dispatch.get(this, "DataSource"); return Dispatch.get(this, "DataSource");
} }
public void setDataSource(Variant ppunkDataSource) public void setDataSource(Variant ppunkDataSource) {
{
Dispatch.put(this, "DataSource", ppunkDataSource); Dispatch.put(this, "DataSource", ppunkDataSource);
} }
public void Save(String FileName, int PersistFormat) public void Save(String FileName, int PersistFormat) {
{
Dispatch.call(this, "Save", FileName, new Variant(PersistFormat)); Dispatch.call(this, "Save", FileName, new Variant(PersistFormat));
} }
public Variant getActiveCommand() public Variant getActiveCommand() {
{
return Dispatch.get(this, "ActiveCommand"); return Dispatch.get(this, "ActiveCommand");
} }
public void setStayInSync(boolean pb) public void setStayInSync(boolean pb) {
{
Dispatch.put(this, "StayInSync", new Variant(pb)); Dispatch.put(this, "StayInSync", new Variant(pb));
} }
public boolean getStayInSync() public boolean getStayInSync() {
{
return Dispatch.get(this, "StayInSync").getBoolean(); return Dispatch.get(this, "StayInSync").getBoolean();
} }
public String GetString(int StringFormat, int NumRows, String ColumnDelimeter, String RowDelimeter, String NullExpr) public String GetString(int StringFormat, int NumRows,
{ String ColumnDelimeter, String RowDelimeter, String NullExpr) {
return Dispatch.call(this, "GetString", new Variant(StringFormat), return Dispatch.call(this, "GetString", new Variant(StringFormat),
new Variant(NumRows), ColumnDelimeter, RowDelimeter, NullExpr).toString(); new Variant(NumRows), ColumnDelimeter, RowDelimeter, NullExpr)
.toString();
} }
public String getDataMember() public String getDataMember() {
{
return Dispatch.get(this, "DataMember").toString(); return Dispatch.get(this, "DataMember").toString();
} }
public void setDataMember(String pl) public void setDataMember(String pl) {
{
Dispatch.put(this, "DataMember", new Variant(pl)); Dispatch.put(this, "DataMember", new Variant(pl));
} }
public int CompareBookmarks(Variant Bookmark1, Variant Bookmark2) public int CompareBookmarks(Variant Bookmark1, Variant Bookmark2) {
{ return Dispatch.call(this, "CompareBookmarks", Bookmark1, Bookmark2)
return Dispatch.call(this, "CompareBookmarks", Bookmark1, Bookmark2).getInt(); .getInt();
} }
public Recordset Clone(int LockType) public Recordset Clone(int LockType) {
{ return new Recordset(Dispatch
return new Recordset(Dispatch.call(this, "Clone", .call(this, "Clone", new Variant(LockType)).toDispatch());
new Variant(LockType)).toDispatch());
} }
public void Resync(int AffectRecords, int ResyncValues) public void Resync(int AffectRecords, int ResyncValues) {
{ Dispatch.call(this, "Resync", new Variant(AffectRecords), new Variant(
Dispatch.call(this, "Resync", new Variant(AffectRecords), new Variant(ResyncValues)); ResyncValues));
} }
public void Seek(Variant KeyValues, int SeekOption) public void Seek(Variant KeyValues, int SeekOption) {
{
Dispatch.call(this, "Seek", KeyValues, new Variant(SeekOption)); Dispatch.call(this, "Seek", KeyValues, new Variant(SeekOption));
} }
public void setIndex(String pl) public void setIndex(String pl) {
{
Dispatch.put(this, "Index", new Variant(pl)); Dispatch.put(this, "Index", new Variant(pl));
} }
public String getIndex() public String getIndex() {
{
return Dispatch.get(this, "Index)").toString(); return Dispatch.get(this, "Index)").toString();
} }
} }

View File

@@ -1,23 +1,19 @@
package com.jacob.samples.ado; package com.jacob.samples.ado;
import com.jacob.com.*;
public class test import com.jacob.com.Variant;
{
public static void printRS(Recordset rs) public class test {
{ public static void printRS(Recordset rs) {
Fields fs = rs.getFields(); Fields fs = rs.getFields();
for (int i=0;i<fs.getCount();i++) for (int i = 0; i < fs.getCount(); i++) {
{
System.out.print(fs.getItem(i).getName() + " "); System.out.print(fs.getItem(i).getName() + " ");
} }
System.out.println(""); System.out.println("");
rs.MoveFirst(); rs.MoveFirst();
while (!rs.getEOF()) while (!rs.getEOF()) {
{ for (int i = 0; i < fs.getCount(); i++) {
for(int i=0;i<fs.getCount();i++)
{
Field f = fs.getItem(i); Field f = fs.getItem(i);
Variant v = f.getValue(); Variant v = f.getValue();
System.out.print(v + " "); System.out.print(v + " ");
@@ -28,8 +24,7 @@ public class test
} }
// open a recordset directly // open a recordset directly
public static void getRS(String con, String query) public static void getRS(String con, String query) {
{
System.out.println("Recordset Open"); System.out.println("Recordset Open");
Recordset rs = new Recordset(); Recordset rs = new Recordset();
rs.Open(new Variant(query), new Variant(con)); rs.Open(new Variant(query), new Variant(con));
@@ -38,8 +33,7 @@ public class test
// create connection and command objects and use them // create connection and command objects and use them
// to get a recordset // to get a recordset
public static void getCommand(String con, String query) public static void getCommand(String con, String query) {
{
System.out.println("Command+Connection -> Recordset"); System.out.println("Command+Connection -> Recordset");
Connection c = new Connection(); Connection c = new Connection();
c.setConnectionString(con); c.setConnectionString(con);
@@ -53,8 +47,7 @@ public class test
c.Close(); c.Close();
} }
public static void main(String[] args) public static void main(String[] args) {
{
String connectStr = "DRIVER=SQL Server;SERVER=DANADLER;UID=sa;PWD=;WSID=DANADLER;DATABASE=pubs"; String connectStr = "DRIVER=SQL Server;SERVER=DANADLER;UID=sa;PWD=;WSID=DANADLER;DATABASE=pubs";
String queryStr = "select * from authors"; String queryStr = "select * from authors";
getCommand(connectStr, queryStr); getCommand(connectStr, queryStr);

View File

@@ -1,11 +1,15 @@
package com.jacob.samples.applet; package com.jacob.samples.applet;
import java.awt.*; import java.applet.Applet;
import java.awt.event.*; import java.awt.Button;
import java.applet.*; import java.awt.FlowLayout;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import com.jacob.com.*; import com.jacob.activeX.ActiveXComponent;
import com.jacob.activeX.*; import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
/** /**
* Applet test case * Applet test case
@@ -38,7 +42,9 @@ public class AppTest extends Applet implements ActionListener {
/** /**
* action method that receives button actions * action method that receives button actions
* @param ev the event *
* @param ev
* the event
*/ */
public void actionPerformed(ActionEvent ev) { public void actionPerformed(ActionEvent ev) {
if (sC == null) { if (sC == null) {

View File

@@ -1,13 +1,22 @@
package com.jacob.samples.atl; package com.jacob.samples.atl;
import com.jacob.com.*; import com.jacob.activeX.ActiveXComponent;
import com.jacob.activeX.*; import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
class MultiFaceTest { class MultiFaceTest {
/**
* standard main() test program
*
* @param args
* the command line arguments
*/
public static void main(String[] args) { public static void main(String[] args) {
// this method has been deprecated as being unreliable. // this method has been deprecated as being unreliable.
// shutdown should be done through other means // shutdown should be done through other means
// whoever wrote this example should explain what this was intended to do // whoever wrote this example should explain what this was intended to
// do
// System.runFinalizersOnExit(true); // System.runFinalizersOnExit(true);
ActiveXComponent mf = new ActiveXComponent("MultiFace.Face"); ActiveXComponent mf = new ActiveXComponent("MultiFace.Face");

View File

@@ -1,18 +1,26 @@
package com.jacob.samples.office; package com.jacob.samples.office;
import com.jacob.com.*; import com.jacob.activeX.ActiveXComponent;
import com.jacob.activeX.*; import com.jacob.com.ComThread;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
/** /**
* Sample test program snagged out of a question on the sun discussion area. * Sample test program snagged out of a question on the sun discussion area.
* <p> * <p>
* May need to run with some command line options (including from inside Eclipse). * May need to run with some command line options (including from inside
* Look in the docs area at the Jacob usage document for command line options. * Eclipse). Look in the docs area at the Jacob usage document for command line
* options.
*/ */
public class ExcelDispatchTest { public class ExcelDispatchTest {
public static void main(String[] args) /**
{ * main run loop for test program
*
* @param args
* standard command line arguments
*/
public static void main(String[] args) {
ComThread.InitSTA(); ComThread.InitSTA();
ActiveXComponent xl = new ActiveXComponent("Excel.Application"); ActiveXComponent xl = new ActiveXComponent("Excel.Application");
@@ -24,11 +32,9 @@ public class ExcelDispatchTest {
Dispatch workbook = Dispatch.get(workbooks, "Add").toDispatch(); Dispatch workbook = Dispatch.get(workbooks, "Add").toDispatch();
Dispatch sheet = Dispatch.get(workbook, "ActiveSheet").toDispatch(); Dispatch sheet = Dispatch.get(workbook, "ActiveSheet").toDispatch();
Dispatch a1 = Dispatch.invoke(sheet, "Range", Dispatch.Get, Dispatch a1 = Dispatch.invoke(sheet, "Range", Dispatch.Get,
new Object[] {"A1"}, new Object[] { "A1" }, new int[1]).toDispatch();
new int[1]).toDispatch();
Dispatch a2 = Dispatch.invoke(sheet, "Range", Dispatch.Get, Dispatch a2 = Dispatch.invoke(sheet, "Range", Dispatch.Get,
new Object[] {"A2"}, new Object[] { "A2" }, new int[1]).toDispatch();
new int[1]).toDispatch();
Dispatch.put(a1, "Value", "123.456"); Dispatch.put(a1, "Value", "123.456");
Dispatch.put(a2, "Formula", "=A1*2"); Dispatch.put(a2, "Formula", "=A1*2");
System.out.println("a1 from excel:" + Dispatch.get(a1, "Value")); System.out.println("a1 from excel:" + Dispatch.get(a1, "Value"));

View File

@@ -7,8 +7,7 @@ import com.jacob.com.Dispatch;
/** /**
* Snippet to show Visio print dialog * Snippet to show Visio print dialog
* <p> * <p>
* Sample submitted by fatbuttlarry in SourceForge 1803140 * Sample submitted by fatbuttlarry in SourceForge 1803140 as part of bug report
* as part of bug report
* <p> * <p>
* Tested with Java 6.0SE and MS Office 2003 ** Note: 1010 = VB's * Tested with Java 6.0SE and MS Office 2003 ** Note: 1010 = VB's
* visCmdFilePrint constant * visCmdFilePrint constant
@@ -26,8 +25,7 @@ public class VisioPrintTest {
// create a blank document // create a blank document
Dispatch.call(oDocuments, "Add", ""); Dispatch.call(oDocuments, "Add", "");
try { try {
Dispatch.call(oActiveX, "DoCmd", new Integer(1010)) Dispatch.call(oActiveX, "DoCmd", new Integer(1010)).getInt();
.getInt();
System.out.println("User hit the ok button."); System.out.println("User hit the ok button.");
} catch (ComFailException e) { } catch (ComFailException e) {
System.out.println("User hit the cancel button: " + e); System.out.println("User hit the cancel button: " + e);
@@ -37,7 +35,12 @@ public class VisioPrintTest {
return; return;
} }
/** quick main() to test this */ /**
* quick main() to test this
*
* @param args
* standard command line arguments
*/
public static void main(String[] args) { public static void main(String[] args) {
VisioPrintTest testObject = new VisioPrintTest(); VisioPrintTest testObject = new VisioPrintTest();
testObject.testPrintDialog(); testObject.testPrintDialog();

View File

@@ -22,7 +22,8 @@ public class WordDocumentProperties {
private Dispatch builtInDocProps; private Dispatch builtInDocProps;
//the doucments object is important in any real app but this demo doesn't use it // the doucments object is important in any real app but this demo doesn't
// use it
// private Dispatch documents; // private Dispatch documents;
private Dispatch document; private Dispatch document;
@@ -49,7 +50,7 @@ public class WordDocumentProperties {
wordObject = objWord.getObject(); wordObject = objWord.getObject();
// Create a Dispatch Parameter to hide the document that is opened // Create a Dispatch Parameter to hide the document that is opened
Dispatch.put((Dispatch) wordObject, "Visible", new Variant(false)); Dispatch.put(wordObject, "Visible", new Variant(false));
// Instantiate the Documents Property // Instantiate the Documents Property
Dispatch documents = objWord.getProperty("Documents").toDispatch(); Dispatch documents = objWord.getProperty("Documents").toDispatch();
@@ -97,8 +98,8 @@ public class WordDocumentProperties {
*/ */
public String getCustomProperty(String cusPropName) { public String getCustomProperty(String cusPropName) {
try { try {
cusPropName = Dispatch.call((Dispatch) custDocprops, "Item", cusPropName = Dispatch.call(custDocprops, "Item", cusPropName)
cusPropName).toString(); .toString();
} catch (ComException e) { } catch (ComException e) {
// Do nothing // Do nothing
cusPropName = null; cusPropName = null;
@@ -115,7 +116,7 @@ public class WordDocumentProperties {
*/ */
public String getBuiltInProperty(String builtInPropName) { public String getBuiltInProperty(String builtInPropName) {
try { try {
builtInPropName = Dispatch.call((Dispatch) builtInDocProps, "Item", builtInPropName = Dispatch.call(builtInDocProps, "Item",
builtInPropName).toString(); builtInPropName).toString();
} catch (ComException e) { } catch (ComException e) {
// Do nothing // Do nothing
@@ -127,6 +128,7 @@ public class WordDocumentProperties {
/** /**
* simple main program that gets some properties and prints them out * simple main program that gets some properties and prints them out
*
* @param args * @param args
*/ */
public static void main(String[] args) { public static void main(String[] args) {

View File

@@ -5,10 +5,13 @@ package com.jacob.samples.outlook;
* Christopher Brind <christopher.brind@morse.com> * Christopher Brind <christopher.brind@morse.com>
*/ */
import com.jacob.com.*; import com.jacob.activeX.ActiveXComponent;
import com.jacob.activeX.*; import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
/**
* sample class to show simple outlook manipulation
*/
public class Outlook { public class Outlook {
private static String pad(int i) { private static String pad(int i) {
@@ -21,13 +24,16 @@ public class Outlook {
return sb.toString(); return sb.toString();
} }
private static void recurseFolders(int iIndent, Dispatch o) { private static void recurseFolders(int iIndent, Dispatch o) {
if (o == null) return; if (o == null) {
return;
}
Dispatch oFolders = Dispatch.get(o, "Folders").toDispatch(); Dispatch oFolders = Dispatch.get(o, "Folders").toDispatch();
// System.out.println("oFolders=" + oFolders); // System.out.println("oFolders=" + oFolders);
if (oFolders == null) return; if (oFolders == null) {
return;
}
Dispatch oFolder = Dispatch.get(oFolders, "GetFirst").toDispatch(); Dispatch oFolder = Dispatch.get(oFolders, "GetFirst").toDispatch();
do { do {
@@ -44,7 +50,13 @@ public class Outlook {
} }
/**
* standard run loop
*
* @param asArgs
* command line arguments
* @throws Exception
*/
public static void main(String asArgs[]) throws Exception { public static void main(String asArgs[]) throws Exception {
System.out.println("Outlook: IN"); System.out.println("Outlook: IN");
@@ -66,4 +78,3 @@ public class Outlook {
} }
} }

View File

@@ -10,9 +10,11 @@ import com.jacob.com.Variant;
/** /**
* Example VB script that grabs hard drive properties. * Example VB script that grabs hard drive properties.
* <p> * <p>
* Source Forge posting http://sourceforge.net/forum/forum.php?thread_id=1785936&forum_id=375946 * Source Forge posting
* http://sourceforge.net/forum/forum.php?thread_id=1785936&forum_id=375946
* <p> * <p>
* Enhance by clay_shooter with info from http://msdn2.microsoft.com/en-us/library/d6dw7aeh.aspx * Enhance by clay_shooter with info from
* http://msdn2.microsoft.com/en-us/library/d6dw7aeh.aspx
* *
* @author qstephenson * @author qstephenson
* *
@@ -20,7 +22,8 @@ import com.jacob.com.Variant;
public class DiskUtils { public class DiskUtils {
/** formatters aren't thread safe but the sample only has one thread */ /** formatters aren't thread safe but the sample only has one thread */
private static DecimalFormat sizeFormatter = new DecimalFormat("###,###,###,###"); private static DecimalFormat sizeFormatter = new DecimalFormat(
"###,###,###,###");
/** a pointer to the scripting file system object */ /** a pointer to the scripting file system object */
private ActiveXComponent fileSystemApp = null; private ActiveXComponent fileSystemApp = null;
@@ -30,6 +33,9 @@ public class DiskUtils {
/** /**
* Standard constructor * Standard constructor
*
* @param drive
* the drive to run the test against.
*/ */
public DiskUtils(String drive) { public DiskUtils(String drive) {
setUp(drive); setUp(drive);
@@ -37,12 +43,14 @@ public class DiskUtils {
/** /**
* open the connection to the scripting object * open the connection to the scripting object
*
* @param drive
* the drive to run the test against
*/ */
public void setUp(String drive) { public void setUp(String drive) {
if (fileSystemApp == null) { if (fileSystemApp == null) {
ComThread.InitSTA(); ComThread.InitSTA();
fileSystemApp = new ActiveXComponent( fileSystemApp = new ActiveXComponent("Scripting.FileSystemObject");
"Scripting.FileSystemObject");
myDrive = Dispatch.call(fileSystemApp, "GetDrive", drive) myDrive = Dispatch.call(fileSystemApp, "GetDrive", drive)
.toDispatch(); .toDispatch();
} }
@@ -57,6 +65,7 @@ public class DiskUtils {
/** /**
* convenience method * convenience method
*
* @return driver serial number * @return driver serial number
*/ */
public int getSerialNumber() { public int getSerialNumber() {
@@ -64,10 +73,11 @@ public class DiskUtils {
} }
/** /**
* Convenience method. * Convenience method. We go through these formatting hoops so we can make
* We go through these formatting hoops so we can make the size string pretty. * the size string pretty. We wouldn't have to do that if we didn't mind
* We wouldn't have to do that if we didn't mind long strings with Exxx at the end * long strings with Exxx at the end or the fact that the value returned can
* or the fact that the value returned can vary in size based on the size of the disk. * vary in size based on the size of the disk.
*
* @return driver total size of the disk * @return driver total size of the disk
*/ */
public String getTotalSize() { public String getTotalSize() {
@@ -82,9 +92,10 @@ public class DiskUtils {
} }
/** /**
* Convenience method. * Convenience method. We wouldn't have to do that if we didn't mind long
* We wouldn't have to do that if we didn't mind long strings with Exxx at the end * strings with Exxx at the end or the fact that the value returned can vary
* or the fact that the value returned can vary in size based on the size of the disk. * in size based on the size of the disk.
*
* @return driver free size of the disk * @return driver free size of the disk
*/ */
public String getFreeSpace() { public String getFreeSpace() {
@@ -116,17 +127,26 @@ public class DiskUtils {
public String getVolumeName() { public String getVolumeName() {
return Dispatch.get(myDrive, "VolumeName").getString(); return Dispatch.get(myDrive, "VolumeName").getString();
} }
/** /**
* Simple main program that creates a DiskUtils object and queries for the C: drive * Simple main program that creates a DiskUtils object and queries for the
* C: drive
*
* @param args
* standard command line arguments
*/ */
public static void main(String[] args) { public static void main(String[] args) {
// DiskUtils utilConnection = new DiskUtils("F"); // DiskUtils utilConnection = new DiskUtils("F");
DiskUtils utilConnection = new DiskUtils("C"); DiskUtils utilConnection = new DiskUtils("C");
System.out.println("Disk serial number is: "+ utilConnection.getSerialNumber()); System.out.println("Disk serial number is: "
System.out.println("FileSystem is: "+ utilConnection.getFileSystemType()); + utilConnection.getSerialNumber());
System.out.println("FileSystem is: "
+ utilConnection.getFileSystemType());
System.out.println("Volume Name is: " + utilConnection.getVolumeName()); System.out.println("Volume Name is: " + utilConnection.getVolumeName());
System.out.println("Disk total size is: "+ utilConnection.getTotalSize()); System.out.println("Disk total size is: "
System.out.println("Disk free space is: "+ utilConnection.getFreeSpace()); + utilConnection.getTotalSize());
System.out.println("Disk free space is: "
+ utilConnection.getFreeSpace());
utilConnection.tearDown(); utilConnection.tearDown();
} }
} }

View File

@@ -17,13 +17,17 @@ import com.jacob.com.Variant;
*/ */
public class SystemMonitor { public class SystemMonitor {
/**
* example run loop method called by main()
*/
public void runMonitor() { public void runMonitor() {
ActiveXComponent wmi = null; ActiveXComponent wmi = null;
wmi = new ActiveXComponent("WbemScripting.SWbemLocator"); wmi = new ActiveXComponent("WbemScripting.SWbemLocator");
// no connection parameters means to connect to the local machine // no connection parameters means to connect to the local machine
Variant conRet = wmi.invoke("ConnectServer"); Variant conRet = wmi.invoke("ConnectServer");
// the author liked the ActiveXComponent api style over the Dispatch style // the author liked the ActiveXComponent api style over the Dispatch
// style
ActiveXComponent wmiconnect = new ActiveXComponent(conRet.toDispatch()); ActiveXComponent wmiconnect = new ActiveXComponent(conRet.toDispatch());
// the WMI supports a query language. // the WMI supports a query language.
@@ -40,7 +44,7 @@ public class SystemMonitor {
while (enumVariant.hasMoreElements()) { while (enumVariant.hasMoreElements()) {
resultString = ""; resultString = "";
item = enumVariant.Next().toDispatch(); item = enumVariant.nextElement().toDispatch();
String categoryString = Dispatch.call(item, "CategoryString") String categoryString = Dispatch.call(item, "CategoryString")
.toString(); .toString();
String messageString = Dispatch.call(item, "Message").toString(); String messageString = Dispatch.call(item, "Message").toString();
@@ -48,17 +52,21 @@ public class SystemMonitor {
.toString(); .toString();
String eventUser = Dispatch.call(item, "User").toString(); String eventUser = Dispatch.call(item, "User").toString();
String eventType = Dispatch.call(item, "Type").toString(); String eventType = Dispatch.call(item, "Type").toString();
resultString += "TimeGenerated: "+ timeGenerated resultString += "TimeGenerated: " + timeGenerated + " Category: "
+ " Category: " + categoryString + categoryString + " User: " + eventUser + " EventType: "
+ " User: " + eventUser + eventType + " Message:" + messageString;
+ " EventType: "+ eventType
+ " Message:" + messageString;
System.out.println(resultString); System.out.println(resultString);
} }
} }
/**
* sample's main program
*
* @param args
* command line arguments
*/
public static void main(String[] args) { public static void main(String[] args) {
SystemMonitor utilConnection = new SystemMonitor(); SystemMonitor utilConnection = new SystemMonitor();
utilConnection.runMonitor(); utilConnection.runMonitor();

View File

@@ -1,38 +1,54 @@
package com.jacob.samples.visio; package com.jacob.samples.visio;
import com.jacob.com.*;
import com.jacob.activeX.*;
import java.io.File; import java.io.File;
import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.DispatchEvents;
import com.jacob.com.Variant;
/** /**
* Created as part of sourceforge 1386454 to demonstrate returning values in event handlers * Created as part of sourceforge 1386454 to demonstrate returning values in
* event handlers
*
* @author miles@rowansoftware.net * @author miles@rowansoftware.net
* *
* This class represents the visio app itself * This class represents the visio app itself
*/ */
public class VisioApp extends ActiveXComponent { public class VisioApp extends ActiveXComponent {
/**
* constructor that spins up Visio
*
* @throws VisioException
*/
public VisioApp() throws VisioException { public VisioApp() throws VisioException {
super("Visio.Application"); super("Visio.Application");
setVisible(false); setVisible(false);
} }
/** /**
* creates a DispatchEvents boject to register o as a listener * creates a DispatchEvents object to register o as a listener
*
* @param o * @param o
*/ */
public void addEventListener(VisioEventListener o) { public void addEventListener(VisioEventListener o) {
DispatchEvents events = new DispatchEvents(this, o); DispatchEvents events = new DispatchEvents(this, o);
if (events == null) { if (events == null) {
System.out.println("You should never get null back when creating a DispatchEvents object"); System.out
.println("You should never get null back when creating a DispatchEvents object");
} }
} }
/**
* opens the passed in file in Visio
*
* @param f
* @throws VisioException
*/
public void open(File f) throws VisioException { public void open(File f) throws VisioException {
try { try {
ActiveXComponent documents = new ActiveXComponent(getProperty("Documents").toDispatch()); ActiveXComponent documents = new ActiveXComponent(getProperty(
"Documents").toDispatch());
Variant[] args = new Variant[1]; Variant[] args = new Variant[1];
args[0] = new Variant(f.getPath()); args[0] = new Variant(f.getPath());
documents.invoke("Open", args); documents.invoke("Open", args);
@@ -42,9 +58,15 @@ public class VisioApp extends ActiveXComponent {
} }
} }
/**
* tells Visio to save the drawing
*
* @throws VisioException
*/
public void save() throws VisioException { public void save() throws VisioException {
try { try {
ActiveXComponent document = new ActiveXComponent(getProperty("ActiveDocument").toDispatch()); ActiveXComponent document = new ActiveXComponent(getProperty(
"ActiveDocument").toDispatch());
document.invoke("Save"); document.invoke("Save");
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
@@ -53,20 +75,28 @@ public class VisioApp extends ActiveXComponent {
} }
/** /**
* terminates visio * terminates Visio
*/ */
public void quit() { public void quit() {
System.out.println("Received quit()"); System.out.println("Received quit()");
// there can't be any open documents for this to work // there can't be any open documents for this to work
// you'll get a visio error if you don't close them // you'll get a visio error if you don't close them
ActiveXComponent document = new ActiveXComponent(getProperty("ActiveDocument").toDispatch()); ActiveXComponent document = new ActiveXComponent(getProperty(
"ActiveDocument").toDispatch());
document.invoke("Close"); document.invoke("Close");
invoke("Quit"); invoke("Quit");
} }
/**
* runs the Visio export command
*
* @param f
* @throws VisioException
*/
public void export(File f) throws VisioException { public void export(File f) throws VisioException {
try { try {
ActiveXComponent document = new ActiveXComponent(getProperty("ActivePage").toDispatch()); ActiveXComponent document = new ActiveXComponent(getProperty(
"ActivePage").toDispatch());
Variant[] args = new Variant[1]; Variant[] args = new Variant[1];
args[0] = new Variant(f.getPath()); args[0] = new Variant(f.getPath());
document.invoke("Export", args); document.invoke("Export", args);
@@ -75,6 +105,12 @@ public class VisioApp extends ActiveXComponent {
} }
} }
/**
* makes Visio visible so the user can watch
*
* @param b
* @throws VisioException
*/
public void setVisible(boolean b) throws VisioException { public void setVisible(boolean b) throws VisioException {
try { try {
setProperty("Visible", new Variant(b)); setProperty("Visible", new Variant(b));

View File

@@ -1,32 +1,51 @@
package com.jacob.samples.visio; package com.jacob.samples.visio;
import java.io.*; import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/** /**
* Created as part of sourceforge 1386454 to demonstrate returning values in event handlers * Created as part of sourceforge 1386454 to demonstrate returning values in
* event handlers
*
* @author miles@rowansoftware.net * @author miles@rowansoftware.net
* *
* This singleton isolates the demo app from the Visio instance object so that * This singleton isolates the demo app from the Visio instance object so that
* you can't try and send messages to a dead Visio instance after quit() has been * you can't try and send messages to a dead Visio instance after quit() has
* called. Direct consumption of VisioApp would mean you could quit but would * been called. Direct consumption of VisioApp would mean you could quit but
* still have a handle to the no longer connected application proxy * would still have a handle to the no longer connected application proxy
* *
*/ */
public class VisioAppFacade { public class VisioAppFacade {
private VisioApp app; private VisioApp app;
private static VisioAppFacade instance; private static VisioAppFacade instance;
/** extension for image files */
public static final String IMAGE_EXT = ".jpg"; public static final String IMAGE_EXT = ".jpg";
/** extension for visio files */
public static final String VISIO_EXT = ".vsd"; public static final String VISIO_EXT = ".vsd";
/** the buffer size when we want to read stuff in */
public static final int BUFFER_SIZE = 2048; public static final int BUFFER_SIZE = 2048;
/**
* Wrapper around Visio
*
* @throws VisioException
*/
private VisioAppFacade() throws VisioException { private VisioAppFacade() throws VisioException {
this.app = new VisioApp(); this.app = new VisioApp();
app.addEventListener(new VisioEventAdapter(app)); app.addEventListener(new VisioEventAdapter(app));
} }
/**
* @return the singleton instance of Visio
* @throws VisioException
*/
public static VisioAppFacade getInstance() throws VisioException { public static VisioAppFacade getInstance() throws VisioException {
if (instance == null) { if (instance == null) {
instance = new VisioAppFacade(); instance = new VisioAppFacade();
@@ -34,6 +53,13 @@ public class VisioAppFacade {
return instance; return instance;
} }
/**
* creates a preview in a temp file and returns the raw data.
*
* @param visioData
* @return raw preview data
* @throws VisioException
*/
public byte[] createPreview(byte[] visioData) throws VisioException { public byte[] createPreview(byte[] visioData) throws VisioException {
byte[] preview; byte[] preview;
File tmpFile; File tmpFile;
@@ -50,6 +76,13 @@ public class VisioAppFacade {
return preview; return preview;
} }
/**
* reads a preview from a saved file
*
* @param visioFile
* @return raw preview data
* @throws VisioException
*/
public byte[] createPreview(File visioFile) throws VisioException { public byte[] createPreview(File visioFile) throws VisioException {
try { try {
File imageFile; File imageFile;
@@ -79,6 +112,13 @@ public class VisioAppFacade {
} while (read > 0); } while (read > 0);
} }
/**
* creates a preview from an input stream
*
* @param in
* @return byte contents of the preview stream
* @throws VisioException
*/
public byte[] createPreview(InputStream in) throws VisioException { public byte[] createPreview(InputStream in) throws VisioException {
byte[] preview; byte[] preview;
// byte[] buff = new byte[2048]; // byte[] buff = new byte[2048];
@@ -100,19 +140,39 @@ public class VisioAppFacade {
return preview; return preview;
} }
/**
* opens the file in Visio and makes the editor visible
*
* @param f
* the reference to the Visio file to be opened
* @throws VisioException
*/
public void editDiagram(File f) throws VisioException { public void editDiagram(File f) throws VisioException {
app.open(f); app.open(f);
app.setVisible(true); app.setVisible(true);
} }
/**
* creates a temporary viso file
*
* @return created visio temporary file
* @throws IOException
*/
private File getTempVisioFile() throws IOException { private File getTempVisioFile() throws IOException {
return File.createTempFile("java", VISIO_EXT); return File.createTempFile("java", VISIO_EXT);
} }
/**
* creates a temporary image file and returns the File object
*
* @return the created image file object
* @throws IOException
*/
private File getTempImageFile() throws IOException { private File getTempImageFile() throws IOException {
return File.createTempFile("java", IMAGE_EXT); return File.createTempFile("java", IMAGE_EXT);
} }
/** exit visio */
public void quit() { public void quit() {
app.quit(); app.quit();
instance = null; instance = null;

View File

@@ -1,20 +1,34 @@
package com.jacob.samples.visio; package com.jacob.samples.visio;
import javax.swing.*;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.File;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
import javax.swing.filechooser.FileFilter; import javax.swing.filechooser.FileFilter;
import com.jacob.com.ComThread; import com.jacob.com.ComThread;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
/** /**
* Created as part of sourceforge 1386454 to demonstrate returning values in event handlers * Created as part of sourceforge 1386454 to demonstrate returning values in
* event handlers
*
* @author miles@rowansoftware.net * @author miles@rowansoftware.net
* <p> * <p>
* This file contains the main() that runs the demo * This file contains the main() that runs the demo
* <p> * <p>
* Look in the docs area at the Jacob usage document for command line options. * Look in the docs area at the Jacob usage document for command line
* options.
*/ */
public class VisioDemo extends JFrame implements ActionListener, WindowListener { public class VisioDemo extends JFrame implements ActionListener, WindowListener {
@@ -37,7 +51,6 @@ public class VisioDemo extends JFrame implements ActionListener, WindowListener
// put this up here so it remembers where we were on the last choose // put this up here so it remembers where we were on the last choose
JFileChooser chooser = null; JFileChooser chooser = null;
public class VisioFileFilter extends FileFilter { public class VisioFileFilter extends FileFilter {
public boolean accept(File f) { public boolean accept(File f) {
if (f.isDirectory()) { if (f.isDirectory()) {
@@ -104,7 +117,9 @@ public class VisioDemo extends JFrame implements ActionListener, WindowListener
try { try {
chooser = new JFileChooser(); chooser = new JFileChooser();
// comment this out if you want it to always go to myDocuments // comment this out if you want it to always go to myDocuments
chooser.setCurrentDirectory(new File(System.getProperty("user.dir"))); chooser
.setCurrentDirectory(new File(System
.getProperty("user.dir")));
chooser.setFileFilter(new VisioFileFilter()); chooser.setFileFilter(new VisioFileFilter());
int returnVal = chooser.showOpenDialog(this); int returnVal = chooser.showOpenDialog(this);
if (returnVal == JFileChooser.APPROVE_OPTION) { if (returnVal == JFileChooser.APPROVE_OPTION) {
@@ -117,8 +132,10 @@ public class VisioDemo extends JFrame implements ActionListener, WindowListener
} }
/** /**
* use this private method instead of initializing on boot up so that instance * use this private method instead of initializing on boot up so that
* and all listeners are created in this thread (event thread) rather than root thread * instance and all listeners are created in this thread (event thread)
* rather than root thread
*
* @return * @return
*/ */
private VisioAppFacade getVisio() { private VisioAppFacade getVisio() {
@@ -132,6 +149,7 @@ public class VisioDemo extends JFrame implements ActionListener, WindowListener
} }
return visioProxy; return visioProxy;
} }
private void showSelectedFilePreview() throws VisioException { private void showSelectedFilePreview() throws VisioException {
if (selectedFile != null) { if (selectedFile != null) {
byte[] image = getVisio().createPreview(selectedFile); byte[] image = getVisio().createPreview(selectedFile);
@@ -160,6 +178,7 @@ public class VisioDemo extends JFrame implements ActionListener, WindowListener
visioProxy.quit(); visioProxy.quit();
} }
} }
public void windowClosing(WindowEvent e) { public void windowClosing(WindowEvent e) {
} }
@@ -172,6 +191,7 @@ public class VisioDemo extends JFrame implements ActionListener, WindowListener
public void windowIconified(WindowEvent e) { public void windowIconified(WindowEvent e) {
System.out.println("Fooboo"); System.out.println("Fooboo");
} }
public void windowOpened(WindowEvent e) { public void windowOpened(WindowEvent e) {
} }
} }

View File

@@ -1,11 +1,15 @@
package com.jacob.samples.visio; package com.jacob.samples.visio;
import com.jacob.com.*;
import com.jacob.com.Variant;
/** /**
* Created as part of sourceforge 1386454 to demonstrate returning values in event handlers * Created as part of sourceforge 1386454 to demonstrate returning values in
* event handlers
*
* @author miles@rowansoftware.net * @author miles@rowansoftware.net
* *
* You can subclass this class and only implement the methods you're interested in * You can subclass this class and only implement the methods you're interested
* in
*/ */
public class VisioEventAdapter implements VisioEventListener { public class VisioEventAdapter implements VisioEventListener {
@@ -16,23 +20,28 @@ public class VisioEventAdapter implements VisioEventListener {
System.out.println("Event listener constructed"); System.out.println("Event listener constructed");
} }
public void BeforeQuit(Variant[] args){ } public void BeforeQuit(Variant[] args) {
}
public void DocumentChanged(Variant[] args) { public void DocumentChanged(Variant[] args) {
System.out.println("documentChanged()"); System.out.println("documentChanged()");
} }
public void DocumentCloseCanceled(Variant[] args){ } public void DocumentCloseCanceled(Variant[] args) {
}
public void DocumentCreated(Variant[] args){ } public void DocumentCreated(Variant[] args) {
}
public void DocumentOpened(Variant[] args) { public void DocumentOpened(Variant[] args) {
System.out.println("DocumentOpened()"); System.out.println("DocumentOpened()");
} }
public void DocumentSaved(Variant[] args){ } public void DocumentSaved(Variant[] args) {
}
public void DocumentSavedAs(Variant[] args){ } public void DocumentSavedAs(Variant[] args) {
}
public Variant QueryCancelDocumentClose(Variant[] args) { public Variant QueryCancelDocumentClose(Variant[] args) {
System.out.println("QueryCancelDocumentClose()"); System.out.println("QueryCancelDocumentClose()");
@@ -40,12 +49,13 @@ public class VisioEventAdapter implements VisioEventListener {
} }
/** /**
* we don't actually let it quit. We block it so * we don't actually let it quit. We block it so that we don't have to
* that we don't have to relaunch when we look at a new document * relaunch when we look at a new document
*/ */
public Variant QueryCancelQuit(Variant[] args) { public Variant QueryCancelQuit(Variant[] args) {
// these may throw VisioException // these may throw VisioException
System.out.println("Saving document, hiding and telling visio not to quit"); System.out
.println("Saving document, hiding and telling visio not to quit");
try { try {
app.save(); app.save();
app.setVisible(false); app.setVisible(false);
@@ -56,4 +66,3 @@ public class VisioEventAdapter implements VisioEventListener {
return new Variant(true); return new Variant(true);
} }
} }

View File

@@ -1,16 +1,17 @@
package com.jacob.samples.visio; package com.jacob.samples.visio;
import com.jacob.com.*;
import com.jacob.com.Variant;
/** /**
* Created as part of sourceforge 1386454 to demonstrate returning values in event handlers * Created as part of sourceforge 1386454 to demonstrate returning values in
* event handlers
*
* @author miles@rowansoftware.net * @author miles@rowansoftware.net
* *
* There are many more Visio events available. See the Microsoft * There are many more Visio events available. See the Microsoft Office SDK
* Office SDK documentation. To receive an event, add a method to this interface * documentation. To receive an event, add a method to this interface whose name
* whose name matches the event name and has only one parameter, Variant[]. * matches the event name and has only one parameter, Variant[]. The JACOB
* The JACOB library will use reflection to call that method when an event is received. * library will use reflection to call that method when an event is received.
*/ */
public interface VisioEventListener { public interface VisioEventListener {
@@ -30,4 +31,3 @@ public interface VisioEventListener {
public Variant QueryCancelQuit(Variant[] args); public Variant QueryCancelQuit(Variant[] args);
} }

View File

@@ -1,10 +1,13 @@
package com.jacob.samples.visio; package com.jacob.samples.visio;
/** /**
* Created as part of sourceforge 1386454 to demonstrate returning values in event handlers * Created as part of sourceforge 1386454 to demonstrate returning values in
* event handlers
*
* @author miles@rowansoftware.net * @author miles@rowansoftware.net
* *
* This extends runtime exception so that we can be sloppy and not put catch blocks everywhere * This extends runtime exception so that we can be sloppy and not put catch
* blocks everywhere
*/ */
public class VisioException extends Exception { public class VisioException extends Exception {
/** /**

View File

@@ -19,35 +19,39 @@
*/ */
package com.jacob.activeX; package com.jacob.activeX;
import com.jacob.com.*; import com.jacob.com.Dispatch;
import com.jacob.com.JacobObject;
import com.jacob.com.Variant;
/** /**
* This class provides a higher level, more object like, wrapper for * This class provides a higher level, more object like, wrapper for top of the
* top of the Dispatch object. The Dispatch class's method essentially * Dispatch object. The Dispatch class's method essentially directly map to
* directly map to Microsoft C API including the first parameter that is * Microsoft C API including the first parameter that is almost always the
* almost always the target of the message. * target of the message. ActiveXComponent assumes the target of every message
* ActiveXComponent assumes the target of every message is the MS * is the MS COM object behind the ActiveXComponent. This removes the need to
* COM object behind the ActiveXComponent. This removes the need * pass the Dispatch object into every method.
* to pass the Dispatch object into every method.
* <p> * <p>
* It is really up to the developer as to whether they want to * It is really up to the developer as to whether they want to use the Dispatch
* use the Dispatch interface or the ActiveXComponent interface. * interface or the ActiveXComponent interface.
* <p> * <p>
* This class simulates com.ms.activeX.ActiveXComponent only in * This class simulates com.ms.activeX.ActiveXComponent only in the sense that
* the senese that it is used for creating Dispatch objects * it is used for creating Dispatch objects
*/ */
public class ActiveXComponent extends Dispatch { public class ActiveXComponent extends Dispatch {
/** /**
* Normally used to create a new connection to a microsoft application. * Normally used to create a new connection to a microsoft application. The
* The passed in parameter is the name of the program as registred * passed in parameter is the name of the program as registered in the
* in the registry. It can also be the object name. * registry. It can also be the object name.
* <p> * <p>
* This constructor causes a new Windows object of the requested * This constructor causes a new Windows object of the requested type to be
* type to be created. The windows CoCreate() function gets called * created. The windows CoCreate() function gets called to create the
* to create the underlying windows object. * underlying windows object.
*
* <pre>
* new ActiveXComponent(&quot;ScriptControl&quot;);
* </pre>
* *
* <pre>new ActiveXComponent("ScriptControl");</pre>
* @param programId * @param programId
*/ */
public ActiveXComponent(String programId) { public ActiveXComponent(String programId) {
@@ -55,9 +59,9 @@ public class ActiveXComponent extends Dispatch {
} }
/** /**
* Creates an active X component that is built on top of the * Creates an active X component that is built on top of the COM pointers
* COM pointers held in the passed in dispatch. * held in the passed in dispatch. This widens the Dispatch object to pick
* This widends the Dispatch object to pick up the ActiveXComponent API * up the ActiveXComponent API
* *
* @param dispatchToBeWrapped * @param dispatchToBeWrapped
*/ */
@@ -74,8 +78,9 @@ public class ActiveXComponent extends Dispatch {
} }
/** /**
* Probably was a cover for something else in the past. * Probably was a cover for something else in the past. Should be
* Should be deprecated. * deprecated.
*
* @return Now it actually returns this exact same object. * @return Now it actually returns this exact same object.
*/ */
public Dispatch getObject() { public Dispatch getObject() {
@@ -83,14 +88,13 @@ public class ActiveXComponent extends Dispatch {
} }
/** /**
* Most code should use the standard ActiveXComponent(String) contructor * Most code should use the standard ActiveXComponent(String) contructor and
* and not this factory method. This method exists for applications * not this factory method. This method exists for applications that need
* that need special behavior. * special behavior. <B>Experimental in release 1.9.2.</B>
* <B>Experimental in release 1.9.2.</B>
* <p> * <p>
* Factory that returns a Dispatch object wrapped around the result * Factory that returns a Dispatch object wrapped around the result of a
* of a CoCreate() call. This differs from the standard constructor * CoCreate() call. This differs from the standard constructor in that it
* in that it throws no exceptions and returns null on failure. * throws no exceptions and returns null on failure.
* <p> * <p>
* This will fail for any prog id with a ":" in it. * This will fail for any prog id with a ":" in it.
* *
@@ -105,28 +109,30 @@ public class ActiveXComponent extends Dispatch {
} catch (Exception e) { } catch (Exception e) {
mCreatedDispatch = null; mCreatedDispatch = null;
if (JacobObject.isDebugEnabled()) { if (JacobObject.isDebugEnabled()) {
JacobObject.debug("Unable to co-create instance of "+pRequestedProgramId); JacobObject.debug("Unable to co-create instance of "
+ pRequestedProgramId);
} }
} }
return mCreatedDispatch; return mCreatedDispatch;
} }
/** /**
* Most code should use the standard ActiveXComponent(String) contructor * Most code should use the standard ActiveXComponent(String) constructor and
* and not this factory method. This method exists for applications * not this factory method. This method exists for applications that need
* that need special behavior. * special behavior. <B>Experimental in release 1.9.2.</B>
* <B>Experimental in release 1.9.2.</B>
* <p> * <p>
* Factory that returns a Dispatch wrapped around the result * Factory that returns a Dispatch wrapped around the result of a
* of a getActiveObject() call. This differs from the standard constructor * getActiveObject() call. This differs from the standard constructor in
* in that it throws no exceptions and returns null on failure. * that it throws no exceptions and returns null on failure.
* <p> * <p>
* This will fail for any prog id with a ":" in it * This will fail for any prog id with a ":" in it
* *
* @param pRequestedProgramId * @param pRequestedProgramId
* @return Dispatch pointer to a COM object or null if wasn't already running * @return Dispatch pointer to a COM object or null if wasn't already
* running
*/ */
public static ActiveXComponent connectToActiveInstance(String pRequestedProgramId){ public static ActiveXComponent connectToActiveInstance(
String pRequestedProgramId) {
ActiveXComponent mCreatedDispatch = null; ActiveXComponent mCreatedDispatch = null;
try { try {
mCreatedDispatch = new ActiveXComponent(); mCreatedDispatch = new ActiveXComponent();
@@ -134,7 +140,8 @@ public class ActiveXComponent extends Dispatch {
} catch (Exception e) { } catch (Exception e) {
mCreatedDispatch = null; mCreatedDispatch = null;
if (JacobObject.isDebugEnabled()) { if (JacobObject.isDebugEnabled()) {
JacobObject.debug("Unable to attach to running instance of "+pRequestedProgramId); JacobObject.debug("Unable to attach to running instance of "
+ pRequestedProgramId);
} }
} }
return mCreatedDispatch; return mCreatedDispatch;
@@ -147,8 +154,8 @@ public class ActiveXComponent extends Dispatch {
super.finalize(); super.finalize();
} }
/*
/*============================================================ * ============================================================
* *
* start of instance based calls to the COM layer * start of instance based calls to the COM layer
* =========================================================== * ===========================================================
@@ -156,27 +163,31 @@ public class ActiveXComponent extends Dispatch {
/** /**
* retrieves a property and returns it as a Variant * retrieves a property and returns it as a Variant
*
* @param propertyName * @param propertyName
* @return variant value of property * @return variant value of property
*/ */
public Variant getProperty(String propertyName) public Variant getProperty(String propertyName) {
{
return Dispatch.get(this, propertyName); return Dispatch.get(this, propertyName);
} }
/** /**
* retrieves a property and returns it as an ActiveX component * retrieves a property and returns it as an ActiveX component
*
* @param propertyName * @param propertyName
* @return Dispatch representing the object under the property name * @return Dispatch representing the object under the property name
*/ */
public ActiveXComponent getPropertyAsComponent(String propertyName) { public ActiveXComponent getPropertyAsComponent(String propertyName) {
return new ActiveXComponent(Dispatch.get(this,propertyName).toDispatch()); return new ActiveXComponent(Dispatch.get(this, propertyName)
.toDispatch());
} }
/** /**
* retrieves a property and returns it as a Boolean * retrieves a property and returns it as a Boolean
* @param propertyName property we are looking up *
* @param propertyName
* property we are looking up
* @return boolean value of property * @return boolean value of property
*/ */
public boolean getPropertyAsBoolean(String propertyName) { public boolean getPropertyAsBoolean(String propertyName) {
@@ -185,7 +196,9 @@ public class ActiveXComponent extends Dispatch {
/** /**
* retrieves a property and returns it as a byte * retrieves a property and returns it as a byte
* @param propertyName property we are looking up *
* @param propertyName
* property we are looking up
* @return byte value of property * @return byte value of property
*/ */
public byte getPropertyAsByte(String propertyName) { public byte getPropertyAsByte(String propertyName) {
@@ -194,6 +207,7 @@ public class ActiveXComponent extends Dispatch {
/** /**
* retrieves a property and returns it as a String * retrieves a property and returns it as a String
*
* @param propertyName * @param propertyName
* @return String value of property * @return String value of property
*/ */
@@ -204,6 +218,7 @@ public class ActiveXComponent extends Dispatch {
/** /**
* retrieves a property and returns it as a int * retrieves a property and returns it as a int
*
* @param propertyName * @param propertyName
* @return the property value as an int * @return the property value as an int
*/ */
@@ -213,27 +228,31 @@ public class ActiveXComponent extends Dispatch {
/** /**
* sets a property on this object * sets a property on this object
* @param propertyName property name *
* @param arg variant value to be set * @param propertyName
* property name
* @param arg
* variant value to be set
*/ */
public void setProperty(String propertyName, Variant arg) public void setProperty(String propertyName, Variant arg) {
{
Dispatch.put(this, propertyName, arg); Dispatch.put(this, propertyName, arg);
} }
/** /**
* sets a property on this object * sets a property on this object
* @param propertyName property name *
* @param arg variant value to be set * @param propertyName
* property name
* @param arg
* variant value to be set
*/ */
public void setProperty(String propertyName, Dispatch arg) public void setProperty(String propertyName, Dispatch arg) {
{
Dispatch.put(this, propertyName, arg); Dispatch.put(this, propertyName, arg);
} }
/** /**
* sets a property to be the value of the string * sets a property to be the value of the string
*
* @param propertyName * @param propertyName
* @param propertyValue * @param propertyValue
*/ */
@@ -243,8 +262,10 @@ public class ActiveXComponent extends Dispatch {
/** /**
* sets a property as a boolean value * sets a property as a boolean value
*
* @param propertyName * @param propertyName
* @param propValue the boolean value we want the prop set to * @param propValue
* the boolean value we want the prop set to
*/ */
public void setProperty(String propertyName, boolean propValue) { public void setProperty(String propertyName, boolean propValue) {
this.setProperty(propertyName, new Variant(propValue)); this.setProperty(propertyName, new Variant(propValue));
@@ -252,8 +273,10 @@ public class ActiveXComponent extends Dispatch {
/** /**
* sets a property as a boolean value * sets a property as a boolean value
*
* @param propertyName * @param propertyName
* @param propValue the boolean value we want the prop set to * @param propValue
* the boolean value we want the prop set to
*/ */
public void setProperty(String propertyName, byte propValue) { public void setProperty(String propertyName, byte propValue) {
this.setProperty(propertyName, new Variant(propValue)); this.setProperty(propertyName, new Variant(propValue));
@@ -261,8 +284,10 @@ public class ActiveXComponent extends Dispatch {
/** /**
* sets the property as an int value * sets the property as an int value
*
* @param propertyName * @param propertyName
* @param propValue the int value we want the prop to be set to. * @param propValue
* the int value we want the prop to be set to.
*/ */
public void setProperty(String propertyName, int propValue) { public void setProperty(String propertyName, int propValue) {
this.setProperty(propertyName, new Variant(propValue)); this.setProperty(propertyName, new Variant(propValue));
@@ -280,8 +305,11 @@ public class ActiveXComponent extends Dispatch {
/** /**
* used by the doc and application listeners to get intelligent logging * used by the doc and application listeners to get intelligent logging
* @param description event description *
* @param args args passed in (variants) * @param description
* event description
* @param args
* args passed in (variants)
* *
*/ */
public void logCallbackEvent(String description, Variant[] args) { public void logCallbackEvent(String description, Variant[] args) {
@@ -296,32 +324,29 @@ public class ActiveXComponent extends Dispatch {
// break out the byref bits if they are on this // break out the byref bits if they are on this
if ((argType & Variant.VariantByref) == Variant.VariantByref) { if ((argType & Variant.VariantByref) == Variant.VariantByref) {
// show the type and the fact that its byref // show the type and the fact that its byref
argString += "("+(args[i].getvt() & ~Variant.VariantByref)+ argString += "("
"/"+Variant.VariantByref+")"; + (args[i].getvt() & ~Variant.VariantByref) + "/"
+ Variant.VariantByref + ")";
} else { } else {
// show the type // show the type
argString += "(" + argType + ")"; argString += "(" + argType + ")";
} }
argString += "="; argString += "=";
if (argType == Variant.VariantDispatch) { if (argType == Variant.VariantDispatch) {
Dispatch foo = (Dispatch)args[i].getDispatch(); Dispatch foo = (args[i].getDispatch());
argString += foo; argString += foo;
} else if ((argType & Variant.VariantBoolean) == } else if ((argType & Variant.VariantBoolean) == Variant.VariantBoolean) {
Variant.VariantBoolean){
// do the boolean thing // do the boolean thing
if ((argType & Variant.VariantByref) == if ((argType & Variant.VariantByref) == Variant.VariantByref) {
Variant.VariantByref){
// boolean by ref // boolean by ref
argString += args[i].getBooleanRef(); argString += args[i].getBooleanRef();
} else { } else {
// boolean by value // boolean by value
argString += args[i].getBoolean(); argString += args[i].getBoolean();
} }
} else if ((argType & Variant.VariantString) == } else if ((argType & Variant.VariantString) == Variant.VariantString) {
Variant.VariantString){
// do the string thing // do the string thing
if ((argType & Variant.VariantByref) == if ((argType & Variant.VariantByref) == Variant.VariantByref) {
Variant.VariantByref){
// string by ref // string by ref
argString += args[i].getStringRef(); argString += args[i].getStringRef();
} else { } else {
@@ -336,13 +361,16 @@ public class ActiveXComponent extends Dispatch {
} }
} }
/*============================================================== /*
* ==============================================================
* *
* covers for dispatch call methods * covers for dispatch call methods
*=============================================================*/ * =============================================================
*/
/** /**
* makes a dispatch call for the passed in action and no parameter * makes a dispatch call for the passed in action and no parameter
*
* @param callAction * @param callAction
* @return ActiveXComponent representing the results of the call * @return ActiveXComponent representing the results of the call
*/ */
@@ -352,6 +380,7 @@ public class ActiveXComponent extends Dispatch {
/** /**
* makes a dispatch call for the passed in action and single parameter * makes a dispatch call for the passed in action and single parameter
*
* @param callAction * @param callAction
* @param parameter * @param parameter
* @return ActiveXComponent representing the results of the call * @return ActiveXComponent representing the results of the call
@@ -363,6 +392,7 @@ public class ActiveXComponent extends Dispatch {
/** /**
* makes a dispatch call for the passed in action and single parameter * makes a dispatch call for the passed in action and single parameter
*
* @param callAction * @param callAction
* @param parameter1 * @param parameter1
* @param parameter2 * @param parameter2
@@ -370,12 +400,13 @@ public class ActiveXComponent extends Dispatch {
*/ */
public ActiveXComponent invokeGetComponent(String callAction, public ActiveXComponent invokeGetComponent(String callAction,
Variant parameter1, Variant parameter2) { Variant parameter1, Variant parameter2) {
return new ActiveXComponent(invoke(callAction, return new ActiveXComponent(invoke(callAction, parameter1, parameter2)
parameter1, parameter2).toDispatch()); .toDispatch());
} }
/** /**
* makes a dispatch call for the passed in action and single parameter * makes a dispatch call for the passed in action and single parameter
*
* @param callAction * @param callAction
* @param parameter1 * @param parameter1
* @param parameter2 * @param parameter2
@@ -383,15 +414,14 @@ public class ActiveXComponent extends Dispatch {
* @return ActiveXComponent representing the results of the call * @return ActiveXComponent representing the results of the call
*/ */
public ActiveXComponent invokeGetComponent(String callAction, public ActiveXComponent invokeGetComponent(String callAction,
Variant parameter1, Variant parameter1, Variant parameter2, Variant parameter3) {
Variant parameter2, return new ActiveXComponent(invoke(callAction, parameter1, parameter2,
Variant parameter3){ parameter3).toDispatch());
return new ActiveXComponent(invoke(callAction,
parameter1, parameter2, parameter3).toDispatch());
} }
/** /**
* makes a dispatch call for the passed in action and single parameter * makes a dispatch call for the passed in action and single parameter
*
* @param callAction * @param callAction
* @param parameter1 * @param parameter1
* @param parameter2 * @param parameter2
@@ -400,18 +430,15 @@ public class ActiveXComponent extends Dispatch {
* @return ActiveXComponent representing the results of the call * @return ActiveXComponent representing the results of the call
*/ */
public ActiveXComponent invokeGetComponent(String callAction, public ActiveXComponent invokeGetComponent(String callAction,
Variant parameter1, Variant parameter1, Variant parameter2, Variant parameter3,
Variant parameter2,
Variant parameter3,
Variant parameter4) { Variant parameter4) {
return new ActiveXComponent(invoke(callAction, return new ActiveXComponent(invoke(callAction, parameter1, parameter2,
parameter1, parameter2, parameter3, parameter4) parameter3, parameter4).toDispatch());
.toDispatch());
} }
/** /**
* invokes a single parameter call on this dispatch * invokes a single parameter call on this dispatch that returns no value
* that returns no value *
* @param actionCommand * @param actionCommand
* @param parameter * @param parameter
* @return a Variant but that may be null for some calls * @return a Variant but that may be null for some calls
@@ -421,7 +448,9 @@ public class ActiveXComponent extends Dispatch {
} }
/** /**
* makes a dispatch call to the passed in action with a single boolean parameter * makes a dispatch call to the passed in action with a single boolean
* parameter
*
* @param actionCommand * @param actionCommand
* @param parameter * @param parameter
* @return Variant result * @return Variant result
@@ -432,6 +461,7 @@ public class ActiveXComponent extends Dispatch {
/** /**
* makes a dispatch call to the passed in action with a single int parameter * makes a dispatch call to the passed in action with a single int parameter
*
* @param actionCommand * @param actionCommand
* @param parameter * @param parameter
* @return Variant result of the invoke (Dispatch.call) * @return Variant result of the invoke (Dispatch.call)
@@ -441,33 +471,37 @@ public class ActiveXComponent extends Dispatch {
} }
/** /**
* makes a dispatch call to the passed in action with a string and integer parameter * makes a dispatch call to the passed in action with a string and integer
* (this was put in for some application) * parameter (this was put in for some application)
*
* @param actionCommand * @param actionCommand
* @param parameter1 * @param parameter1
* @param parameter2 * @param parameter2
* @return Variant result * @return Variant result
*/ */
public Variant invoke(String actionCommand, String parameter1, int parameter2){ public Variant invoke(String actionCommand, String parameter1,
return Dispatch.call(this, actionCommand, parameter1, new Variant(parameter2)); int parameter2) {
return Dispatch.call(this, actionCommand, parameter1, new Variant(
parameter2));
} }
/** /**
* makes a dispatch call to the passed in action with two * makes a dispatch call to the passed in action with two integer parameters
* integer parameters
* (this was put in for some application) * (this was put in for some application)
*
* @param actionCommand * @param actionCommand
* @param parameter1 * @param parameter1
* @param parameter2 * @param parameter2
* @return a Variant but that may be null for some calls * @return a Variant but that may be null for some calls
*/ */
public Variant invoke(String actionCommand, public Variant invoke(String actionCommand, int parameter1, int parameter2) {
int parameter1, int parameter2){ return Dispatch.call(this, actionCommand, new Variant(parameter1),
return Dispatch.call(this, actionCommand, new Variant(parameter2));
new Variant(parameter1),new Variant(parameter2));
} }
/** /**
* makes a dispatch call for the passed in action and single parameter * makes a dispatch call for the passed in action and single parameter
*
* @param callAction * @param callAction
* @param parameter * @param parameter
* @return a Variant but that may be null for some calls * @return a Variant but that may be null for some calls
@@ -478,36 +512,35 @@ public class ActiveXComponent extends Dispatch {
/** /**
* makes a dispatch call for the passed in action and two parameter * makes a dispatch call for the passed in action and two parameter
*
* @param callAction * @param callAction
* @param parameter1 * @param parameter1
* @param parameter2 * @param parameter2
* @return a Variant but that may be null for some calls * @return a Variant but that may be null for some calls
*/ */
public Variant invoke(String callAction, public Variant invoke(String callAction, Variant parameter1,
Variant parameter1,
Variant parameter2) { Variant parameter2) {
return Dispatch.call(this, callAction, parameter1, parameter2); return Dispatch.call(this, callAction, parameter1, parameter2);
} }
/** /**
* makes a dispatch call for the passed in action and two parameter * makes a dispatch call for the passed in action and two parameter
*
* @param callAction * @param callAction
* @param parameter1 * @param parameter1
* @param parameter2 * @param parameter2
* @param parameter3 * @param parameter3
* @return Variant result data * @return Variant result data
*/ */
public Variant invoke(String callAction, public Variant invoke(String callAction, Variant parameter1,
Variant parameter1, Variant parameter2, Variant parameter3) {
Variant parameter2, return Dispatch.call(this, callAction, parameter1, parameter2,
Variant parameter3){ parameter3);
return Dispatch.call(this,callAction,
parameter1, parameter2, parameter3);
} }
/** /**
* calls call() with 4 variant parameters * calls call() with 4 variant parameters
*
* @param callAction * @param callAction
* @param parameter1 * @param parameter1
* @param parameter2 * @param parameter2
@@ -515,18 +548,15 @@ public class ActiveXComponent extends Dispatch {
* @param parameter4 * @param parameter4
* @return Variant result data * @return Variant result data
*/ */
public Variant invoke(String callAction, public Variant invoke(String callAction, Variant parameter1,
Variant parameter1, Variant parameter2, Variant parameter3, Variant parameter4) {
Variant parameter2, return Dispatch.call(this, callAction, parameter1, parameter2,
Variant parameter3, parameter3, parameter4);
Variant parameter4){
return Dispatch.call(this,callAction,
parameter1, parameter2, parameter3, parameter4);
} }
/** /**
* makes a dispatch call for the passed in action and no parameter * makes a dispatch call for the passed in action and no parameter
*
* @param callAction * @param callAction
* @return a Variant but that may be null for some calls * @return a Variant but that may be null for some calls
*/ */
@@ -535,16 +565,15 @@ public class ActiveXComponent extends Dispatch {
} }
/** /**
* This is really a cover for call(String,Variant[]) that should be eliminated * This is really a cover for call(String,Variant[]) that should be
* call with a variable number of args mainly used for quit. * eliminated call with a variable number of args mainly used for quit.
*
* @param name * @param name
* @param args * @param args
* @return Variant returned by the invoke (Dispatch.callN) * @return Variant returned by the invoke (Dispatch.callN)
*/ */
public Variant invoke(String name, Variant[] args) public Variant invoke(String name, Variant[] args) {
{
return Dispatch.callN(this, name, args); return Dispatch.callN(this, name, args);
} }
} }

View File

@@ -26,10 +26,10 @@ import com.jacob.com.InvocationProxy;
/** /**
* RELEASE 1.12 EXPERIMENTAL. * RELEASE 1.12 EXPERIMENTAL.
* <p> * <p>
* Use this exactly like the DispatchEvents class. This class plugs in * Use this exactly like the DispatchEvents class. This class plugs in an
* an ActiveXInvocationProxy instead of an InvocationProxy. It is the * ActiveXInvocationProxy instead of an InvocationProxy. It is the
* ActiveXInvocationProxy that implements the reflection calls and invoke * ActiveXInvocationProxy that implements the reflection calls and invoke the
* the found java event callbacks. See ActiveXInvocationProxy for details. * found java event callbacks. See ActiveXInvocationProxy for details.
* *
* *
*/ */
@@ -38,11 +38,14 @@ public class ActiveXDispatchEvents extends DispatchEvents {
/** /**
* This is the most commonly used constructor. * This is the most commonly used constructor.
* <p> * <p>
* Creates the event callback linkage between the the * Creates the event callback linkage between the the MS program represented
* MS program represented by the Dispatch object and the * by the Dispatch object and the Java object that will receive the
* Java object that will receive the callback. * callback.
* @param sourceOfEvent Dispatch object who's MS app will generate callbacks *
* @param eventSink Java object that wants to receive the events * @param sourceOfEvent
* Dispatch object who's MS app will generate callbacks
* @param eventSink
* Java object that wants to receive the events
*/ */
public ActiveXDispatchEvents(Dispatch sourceOfEvent, Object eventSink) { public ActiveXDispatchEvents(Dispatch sourceOfEvent, Object eventSink) {
super(sourceOfEvent, eventSink, null); super(sourceOfEvent, eventSink, null);
@@ -51,39 +54,47 @@ public class ActiveXDispatchEvents extends DispatchEvents {
/** /**
* None of the samples use this constructor. * None of the samples use this constructor.
* <p> * <p>
* Creates the event callback linkage between the the * Creates the event callback linkage between the the MS program represented
* MS program represented by the Dispatch object and the * by the Dispatch object and the Java object that will receive the
* Java object that will receive the callback. * callback.
* @param sourceOfEvent Dispatch object who's MS app will generate callbacks *
* @param eventSink Java object that wants to receive the events * @param sourceOfEvent
* @param progId ??? * Dispatch object who's MS app will generate callbacks
* @param eventSink
* Java object that wants to receive the events
* @param progId
* ???
*/ */
public ActiveXDispatchEvents(Dispatch sourceOfEvent, Object eventSink, String progId) { public ActiveXDispatchEvents(Dispatch sourceOfEvent, Object eventSink,
String progId) {
super(sourceOfEvent, eventSink, progId, null); super(sourceOfEvent, eventSink, progId, null);
} }
/** /**
* Creates the event callback linkage between the the * Creates the event callback linkage between the the MS program represented
* MS program represented by the Dispatch object and the * by the Dispatch object and the Java object that will receive the
* Java object that will receive the callback. * callback.
*
* <pre> * <pre>
* >ActiveXDispatchEvents de = * &gt;ActiveXDispatchEvents de =
* new ActiveXDispatchEvents(someDispatch,someEventHAndler, * new ActiveXDispatchEvents(someDispatch,someEventHAndler,
* "Excel.Application", * &quot;Excel.Application&quot;,
* "C:\\Program Files\\Microsoft Office\\OFFICE11\\EXCEL.EXE"); * &quot;C:\\Program Files\\Microsoft Office\\OFFICE11\\EXCEL.EXE&quot;);
* *
* @param sourceOfEvent Dispatch object who's MS app will generate callbacks * @param sourceOfEvent Dispatch object who's MS app will generate callbacks
* @param eventSink Java object that wants to receive the events * @param eventSink Java object that wants to receive the events
* @param progId , mandatory if the typelib is specified * @param progId , mandatory if the typelib is specified
* @param typeLib The location of the typelib to use * @param typeLib The location of the typelib to use
*
*/ */
public ActiveXDispatchEvents(Dispatch sourceOfEvent, Object eventSink, String progId, String typeLib) public ActiveXDispatchEvents(Dispatch sourceOfEvent, Object eventSink,
{ String progId, String typeLib) {
super(sourceOfEvent, eventSink, progId, typeLib); super(sourceOfEvent, eventSink, progId, typeLib);
} }
/* /*
* (non-Javadoc) * (non-Javadoc)
*
* @see com.jacob.com.DispatchEvents#getInvocationProxy(java.lang.Object) * @see com.jacob.com.DispatchEvents#getInvocationProxy(java.lang.Object)
*/ */
protected InvocationProxy getInvocationProxy(Object pTargetObject) { protected InvocationProxy getInvocationProxy(Object pTargetObject) {

View File

@@ -29,60 +29,67 @@ import com.jacob.com.Variant;
/** /**
* RELEASE 1.12 EXPERIMENTAL. * RELEASE 1.12 EXPERIMENTAL.
* <p> * <p>
* This class that lets event handlers receive events with all java * This class that lets event handlers receive events with all java objects as
* objects as parameters. The standard Jacob event methods all accept an array of * parameters. The standard Jacob event methods all accept an array of Variant
* Variant objects. When using this class, you can set up your event methods * objects. When using this class, you can set up your event methods as regular
* as regular java methods with the correct number of parameters of the correct * java methods with the correct number of parameters of the correct java type.
* java type. This does NOT work for any event that wishes to accept a call * This does NOT work for any event that wishes to accept a call back and modify
* back and modify the calling parameters to tell windows what to do. An example * the calling parameters to tell windows what to do. An example is when an
* is when an event lets the receiver cancel the action by setting a boolean flag * event lets the receiver cancel the action by setting a boolean flag to false.
* to false. The java objects cannot be modified and their values will not be passed * The java objects cannot be modified and their values will not be passed back
* back into the originating Variants even if they could be modified. * into the originating Variants even if they could be modified.
* <p> * <p>
* This class acts as a proxy between the windows event callback mechanism and * This class acts as a proxy between the windows event callback mechanism and
* the Java classes that are looking for events. It assumes that * the Java classes that are looking for events. It assumes that all of the Java
* all of the Java classes that are looking for events implement methods with the * classes that are looking for events implement methods with the same names as
* same names as the windows events and that the implemented methods native * the windows events and that the implemented methods native java objects of
* java objects of the type and order that match the windows documentation. * the type and order that match the windows documentation. The methods can
* The methods can return void or a Variant that * return void or a Variant that will be returned to the calling layer. All
* will be returned to the calling layer. All Event methods that will be * Event methods that will be recognized by InvocationProxyAllEvents have the
* recognized by InvocationProxyAllEvents have the signature * signature
* *
* <code> void eventMethodName(Object,Object...)</code> * <code> void eventMethodName(Object,Object...)</code> or
* or
* <code> Object eventMethodName(Object,Object...)</code> * <code> Object eventMethodName(Object,Object...)</code>
*/ */
public class ActiveXInvocationProxy extends InvocationProxy { public class ActiveXInvocationProxy extends InvocationProxy {
/* /*
* (non-Javadoc) * (non-Javadoc)
* @see com.jacob.com.InvocationProxy#invoke(java.lang.String, com.jacob.com.Variant[]) *
* @see com.jacob.com.InvocationProxy#invoke(java.lang.String,
* com.jacob.com.Variant[])
*/ */
@SuppressWarnings("unchecked")
public Variant invoke(String methodName, Variant targetParameters[]) { public Variant invoke(String methodName, Variant targetParameters[]) {
Variant mVariantToBeReturned = null; Variant mVariantToBeReturned = null;
if (mTargetObject == null) { if (mTargetObject == null) {
// structured programming guidlines say this return should not be up here // structured programming guidlines say this return should not be up
// here
return null; return null;
} }
Class targetClass = mTargetObject.getClass(); Class targetClass = mTargetObject.getClass();
if (methodName == null) { if (methodName == null) {
throw new IllegalArgumentException("InvocationProxy: missing method name"); throw new IllegalArgumentException(
"InvocationProxy: missing method name");
} }
if (targetParameters == null) { if (targetParameters == null) {
throw new IllegalArgumentException("InvocationProxy: missing Variant parameters"); throw new IllegalArgumentException(
"InvocationProxy: missing Variant parameters");
} }
try { try {
Method targetMethod; Method targetMethod;
Object parametersAsJavaObjects[] = getParametersAsJavaObjects(targetParameters); Object parametersAsJavaObjects[] = getParametersAsJavaObjects(targetParameters);
Class parametersAsJavaClasses[] = getParametersAsJavaClasses(parametersAsJavaObjects); Class parametersAsJavaClasses[] = getParametersAsJavaClasses(parametersAsJavaObjects);
targetMethod = targetClass.getMethod(methodName, parametersAsJavaClasses); targetMethod = targetClass.getMethod(methodName,
parametersAsJavaClasses);
if (targetMethod != null) { if (targetMethod != null) {
// protected classes can't be invoked against even if they // protected classes can't be invoked against even if they
// let you grab the method. you could do targetMethod.setAccessible(true); // let you grab the method. you could do
// targetMethod.setAccessible(true);
// but that should be stopped by the security manager // but that should be stopped by the security manager
Object mReturnedByInvocation = null; Object mReturnedByInvocation = null;
mReturnedByInvocation = mReturnedByInvocation = targetMethod.invoke(mTargetObject,
targetMethod.invoke(mTargetObject,parametersAsJavaObjects); parametersAsJavaObjects);
if (mReturnedByInvocation == null) { if (mReturnedByInvocation == null) {
mVariantToBeReturned = null; mVariantToBeReturned = null;
} else if (!(mReturnedByInvocation instanceof Variant)) { } else if (!(mReturnedByInvocation instanceof Variant)) {
@@ -95,11 +102,13 @@ public class ActiveXInvocationProxy extends InvocationProxy {
// what causes this exception? // what causes this exception?
e.printStackTrace(); e.printStackTrace();
} catch (NoSuchMethodException e) { } catch (NoSuchMethodException e) {
// this happens whenever the listener doesn't implement all the methods // this happens whenever the listener doesn't implement all the
// methods
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
// we can throw these inside the catch block so need to re-throw it // we can throw these inside the catch block so need to re-throw it
Exception oneWeShouldToss = new IllegalArgumentException("Unable to map parameters for method "+methodName Exception oneWeShouldToss = new IllegalArgumentException(
+ ": "+e.toString()); "Unable to map parameters for method " + methodName + ": "
+ e.toString());
oneWeShouldToss.printStackTrace(); oneWeShouldToss.printStackTrace();
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
// can't access the method on the target instance for some reason // can't access the method on the target instance for some reason
@@ -113,13 +122,17 @@ public class ActiveXInvocationProxy extends InvocationProxy {
} }
/** /**
* creates a method signature compatible array of classes from an array of parameters * creates a method signature compatible array of classes from an array of
* parameters
*
* @param parametersAsJavaObjects * @param parametersAsJavaObjects
* @return * @return
*/ */
@SuppressWarnings("unchecked")
private Class[] getParametersAsJavaClasses(Object[] parametersAsJavaObjects) { private Class[] getParametersAsJavaClasses(Object[] parametersAsJavaObjects) {
if (parametersAsJavaObjects == null) { if (parametersAsJavaObjects == null) {
throw new IllegalArgumentException("This only works with an array of parameters"); throw new IllegalArgumentException(
"This only works with an array of parameters");
} }
int numParameters = parametersAsJavaObjects.length; int numParameters = parametersAsJavaObjects.length;
Class parametersAsJavaClasses[] = new Class[numParameters]; Class parametersAsJavaClasses[] = new Class[numParameters];
@@ -137,12 +150,14 @@ public class ActiveXInvocationProxy extends InvocationProxy {
/** /**
* converts an array of Variants to their associated Java types * converts an array of Variants to their associated Java types
*
* @param targetParameters * @param targetParameters
* @return * @return
*/ */
private Object[] getParametersAsJavaObjects(Variant[] targetParameters) { private Object[] getParametersAsJavaObjects(Variant[] targetParameters) {
if (targetParameters == null) { if (targetParameters == null) {
throw new IllegalArgumentException("This only works with an array of parameters"); throw new IllegalArgumentException(
"This only works with an array of parameters");
} }
int numParameters = targetParameters.length; int numParameters = targetParameters.length;
Object parametersAsJavaObjects[] = new Object[numParameters]; Object parametersAsJavaObjects[] = new Object[numParameters];
@@ -152,10 +167,12 @@ public class ActiveXInvocationProxy extends InvocationProxy {
parametersAsJavaObjects[parameterIndex] = null; parametersAsJavaObjects[parameterIndex] = null;
} else { } else {
try { try {
parametersAsJavaObjects[parameterIndex] = oneParameterObject.toJavaObject(); parametersAsJavaObjects[parameterIndex] = oneParameterObject
.toJavaObject();
} catch (NotImplementedException nie) { } catch (NotImplementedException nie) {
throw new IllegalArgumentException("Can't convert parameter "+parameterIndex+ throw new IllegalArgumentException(
" type "+oneParameterObject.getvt() "Can't convert parameter " + parameterIndex
+ " type " + oneParameterObject.getvt()
+ " to java object: " + nie.getMessage()); + " to java object: " + nie.getMessage());
} }
} }
@@ -163,5 +180,4 @@ public class ActiveXInvocationProxy extends InvocationProxy {
return parametersAsJavaObjects; return parametersAsJavaObjects;
} }
} }

View File

@@ -22,18 +22,27 @@ package com.jacob.com;
/** /**
* Standard exception thrown by com jni code when there is a problem * Standard exception thrown by com jni code when there is a problem
*/ */
public abstract class ComException extends JacobException public abstract class ComException extends JacobException {
{
// Fields /**
/** COM code initializes this filed with an appropriate return code * COM code initializes this filed with an appropriate return code that was
* that was returned by the underlying com code * returned by the underlying com code
**/ */
protected int hr; protected int hr;
/** No documentation is available at this time. Someone should document this field */ /**
* No documentation is available at this time. Someone should document this
* field
*/
protected int m_helpContext; protected int m_helpContext;
/** No documentation is available at this time. Someone should document this field */ /**
* No documentation is available at this time. Someone should document this
* field
*/
protected String m_helpFile; protected String m_helpFile;
/** No documentation is available at this time. Someone should document this field */ /**
* No documentation is available at this time. Someone should document this
* field
*/
protected String m_source; protected String m_source;
/** /**

View File

@@ -30,6 +30,7 @@ public class ComFailException extends ComException {
/** /**
* Constructor * Constructor
*
* @param hrNew * @param hrNew
*/ */
public ComFailException(int hrNew) { public ComFailException(int hrNew) {
@@ -38,6 +39,7 @@ public class ComFailException extends ComException {
/** /**
* Constructor * Constructor
*
* @param hrNew * @param hrNew
* @param message * @param message
*/ */
@@ -58,6 +60,7 @@ public class ComFailException extends ComException {
/** /**
* Constructor * Constructor
*
* @param hrNew * @param hrNew
* @param description * @param description
* @param source * @param source

View File

@@ -20,9 +20,8 @@
package com.jacob.com; package com.jacob.com;
/** /**
* Represents a COM level thread * Represents a COM level thread This is an abstract class because all the
* This is an abstract class because all the methods are static * methods are static and no instances are ever created.
* and no instances are ever created.
*/ */
public abstract class ComThread { public abstract class ComThread {
private static final int MTA = 0x0; private static final int MTA = 0x0;
@@ -58,6 +57,7 @@ public abstract class ComThread {
* Initialize the current java thread to be part of the Multi-threaded COM * Initialize the current java thread to be part of the Multi-threaded COM
* Apartment, if createMainSTA is true, create a separate MainSTA thread * Apartment, if createMainSTA is true, create a separate MainSTA thread
* that will house all Apartment Threaded components * that will house all Apartment Threaded components
*
* @param createMainSTA * @param createMainSTA
*/ */
public static synchronized void InitMTA(boolean createMainSTA) { public static synchronized void InitMTA(boolean createMainSTA) {
@@ -68,6 +68,7 @@ public abstract class ComThread {
* Initialize the current java thread to be an STA COM Apartment, if * Initialize the current java thread to be an STA COM Apartment, if
* createMainSTA is true, create a separate MainSTA thread that will house * createMainSTA is true, create a separate MainSTA thread that will house
* all Apartment Threaded components * all Apartment Threaded components
*
* @param createMainSTA * @param createMainSTA
*/ */
public static synchronized void InitSTA(boolean createMainSTA) { public static synchronized void InitSTA(boolean createMainSTA) {
@@ -93,6 +94,7 @@ public abstract class ComThread {
/** /**
* Initialize the current java thread to be part of the MTA/STA COM * Initialize the current java thread to be part of the MTA/STA COM
* Apartment * Apartment
*
* @param createMainSTA * @param createMainSTA
* @param mode * @param mode
*/ */
@@ -103,34 +105,47 @@ public abstract class ComThread {
// to avoid COM creating its own // to avoid COM creating its own
startMainSTA(); startMainSTA();
} }
if (JacobObject.isDebugEnabled()){JacobObject.debug("ComThread: before Init: "+mode);} if (JacobObject.isDebugEnabled()) {
JacobObject.debug("ComThread: before Init: " + mode);
}
doCoInitialize(mode); doCoInitialize(mode);
if (JacobObject.isDebugEnabled()){JacobObject.debug("ComThread: after Init: "+mode);} if (JacobObject.isDebugEnabled()) {
JacobObject.debug("ComThread: after Init: " + mode);
}
ROT.addThread(); ROT.addThread();
if (JacobObject.isDebugEnabled()){JacobObject.debug("ComThread: after ROT.addThread: "+mode); } if (JacobObject.isDebugEnabled()) {
JacobObject.debug("ComThread: after ROT.addThread: " + mode);
}
} }
/** /**
* Call CoUninitialize to release this java thread from COM * Call CoUninitialize to release this java thread from COM
*/ */
public static synchronized void Release() { public static synchronized void Release() {
if (JacobObject.isDebugEnabled()){JacobObject.debug("ComThread: before clearObjects"); } if (JacobObject.isDebugEnabled()) {
JacobObject.debug("ComThread: before clearObjects");
}
ROT.clearObjects(); ROT.clearObjects();
if (JacobObject.isDebugEnabled()){JacobObject.debug("ComThread: before UnInit"); } if (JacobObject.isDebugEnabled()) {
JacobObject.debug("ComThread: before UnInit");
}
doCoUninitialize(); doCoUninitialize();
if (JacobObject.isDebugEnabled()){JacobObject.debug("ComThread: after UnInit"); } if (JacobObject.isDebugEnabled()) {
JacobObject.debug("ComThread: after UnInit");
}
} }
/** /**
* @deprecated the java model leave the responsibility of clearing up objects * @deprecated the java model leave the responsibility of clearing up
* to the Garbage Collector. Our programming model should not require that the * objects to the Garbage Collector. Our programming model
* user specifically remove object from the thread. * should not require that the user specifically remove object
* from the thread.
* *
* This will remove an object from the ROT * This will remove an object from the ROT
* @param o * @param o
*/ */
public static synchronized void RemoveObject(JacobObject o) @Deprecated
{ public static synchronized void RemoveObject(JacobObject o) {
ROT.removeObject(o); ROT.removeObject(o);
} }
@@ -145,8 +160,8 @@ public abstract class ComThread {
public static native void doCoUninitialize(); public static native void doCoUninitialize();
/** /**
* load the Jacob DLL. We do this in case COMThread is called before * load the Jacob DLL. We do this in case COMThread is called before any
* any other reference to one of the JacboObject subclasses is made. * other reference to one of the JacboObject subclasses is made.
*/ */
static { static {
LibraryLoader.loadJacobLibrary(); LibraryLoader.loadJacobLibrary();

View File

@@ -0,0 +1,91 @@
package com.jacob.com;
/**
* Most COM bridges use java.lang.Long as their Java data type for COM Currency
* data. This is because COM currency is a 64 bit number where the last 4 digits
* represent the milli-cents. We wanted to support 64 bit Long values for x64
* platforms so that meant we wanted to map Java.LONG to COM.LONG even though it
* only works for 64 bit platforms. The end result was we needed a new
* representation for Money so we have this.
* <p>
* In the future, this should convert to and from BigDecimal or Double
*/
public class Currency {
Long embeddedValue = null;
/**
* constructor that takes a long already in COM representation
*
* @param newValue
*/
public Currency(long newValue) {
embeddedValue = new Long(newValue);
}
/**
* constructor that takes a String already in COM representation
*
* @param newValue
*/
public Currency(String newValue) {
embeddedValue = new Long(newValue);
}
/**
*
* @return the currency as a primitive long
*/
public long longValue() {
return embeddedValue.longValue();
}
/**
* getter to the inner storage so that cmpareTo can work
*
* @return the embedded long value
*/
protected Long getLongValue() {
return embeddedValue;
}
/**
* compares the values of two currencies
*
* @param anotherCurrency
* @return the usual compareTo results
*/
public int compareTo(Currency anotherCurrency) {
return embeddedValue.compareTo(anotherCurrency.getLongValue());
}
/**
* standard comparison
*
* @param o
* must be Currency or Long
* @return the usual compareTo results
*/
public int compareTo(Object o) {
if (o instanceof Currency) {
return compareTo((Currency) o);
} else if (o instanceof Long) {
return embeddedValue.compareTo((Long) o);
} else
throw new IllegalArgumentException(
"Can only compare to Long and Currency not "
+ o.getClass().getName());
}
/**
* {@inheritDoc}
*/
public boolean equals(Object o) {
if (o == null) {
return false;
} else if (compareTo(o) == 0) {
return true;
} else {
return false;
}
}
}

View File

@@ -24,6 +24,7 @@ import java.util.Date;
/** /**
* java / windows date conversion utilities * java / windows date conversion utilities
*
* @author joe * @author joe
* *
*/ */
@@ -31,6 +32,7 @@ public class DateUtilities {
/** /**
* converts a windows time to a Java Date Object * converts a windows time to a Java Date Object
*
* @param comTime * @param comTime
* @return Date object representing the windows time as specified in comTime * @return Date object representing the windows time as specified in comTime
*/ */
@@ -39,14 +41,13 @@ public class DateUtilities {
} }
/** /**
* Convert a COM time from functions Date(), Time(), Now() to a * Convert a COM time from functions Date(), Time(), Now() to a Java time
* Java time (milliseconds). Visual Basic time values are based to * (milliseconds). Visual Basic time values are based to 30.12.1899, Java
* 30.12.1899, Java time values are based to 1.1.1970 (= 0 * time values are based to 1.1.1970 (= 0 milliseconds). The difference is
* milliseconds). The difference is added to the Visual Basic value to * added to the Visual Basic value to get the corresponding Java value. The
* get the corresponding Java value. The Visual Basic double value * Visual Basic double value reads: <day count delta since 30.12.1899>.<1
* reads: <day count delta since 30.12.1899>.<1 day percentage * day percentage fraction>, e.g. "38100.6453" means: 38100 days since
* fraction>, e.g. "38100.6453" means: 38100 days since 30.12.1899 plus * 30.12.1899 plus (24 hours * 0.6453). Example usage:
* (24 hours * 0.6453). Example usage:
* <code>Date javaDate = new Date(toMilliseconds (vbDate));</code>. * <code>Date javaDate = new Date(toMilliseconds (vbDate));</code>.
* *
* @param comTime * @param comTime
@@ -68,15 +69,16 @@ public class DateUtilities {
}// convertWindowsTimeToMilliseconds() }// convertWindowsTimeToMilliseconds()
/** /**
* converts a java date to a windows time object * converts a java date to a windows time object (is this timezone safe?)
* (is this timezone safe?)
* *
* @param javaDate the java date to be converted to windows time * @param javaDate
* the java date to be converted to windows time
* @return the double representing the date in a form windows understands * @return the double representing the date in a form windows understands
*/ */
static public double convertDateToWindowsTime(Date javaDate) { static public double convertDateToWindowsTime(Date javaDate) {
if (javaDate == null) { if (javaDate == null) {
throw new IllegalArgumentException("cannot convert null to windows time"); throw new IllegalArgumentException(
"cannot convert null to windows time");
} }
return convertMillisecondsToWindowsTime(javaDate.getTime()); return convertMillisecondsToWindowsTime(javaDate.getTime());
} }

File diff suppressed because it is too large Load Diff

View File

@@ -20,54 +20,53 @@
package com.jacob.com; package com.jacob.com;
/** /**
* This class creates the scaffolding for event callbacks. * This class creates the scaffolding for event callbacks. Every instance of tis
* Every instance of tis acts as a wrapper around some java object * acts as a wrapper around some java object that wants callbacks from the
* that wants callbacks from the microsoft side. It represents * microsoft side. It represents the connection between Java and COM for
* the connection between Java and COM for callbacks. * callbacks.
* <p> * <p>
* The callback mechanism will take any event that it receives and * The callback mechanism will take any event that it receives and try and find
* try and find a java method with the same name that accepts the * a java method with the same name that accepts the Variant... as a parameter.
* Variant... as a parameter. It will then wrap the call back data * It will then wrap the call back data in the Variant array and call the java
* in the Variant array and call the java method of the object * method of the object that this DispatchEvents object was initialized with.
* that this DispatchEvents object was initialized with.
* <p> * <p>
* Instances of this class are created with "sink object" that * Instances of this class are created with "sink object" that will receive the
* will receive the event messages. The sink object is wrapped in * event messages. The sink object is wrapped in an Invocation handler that
* an Invocation handler that actually receives the messages and then * actually receives the messages and then forwards them on to the "sink
* forwards them on to the "sink object". The constructors recognize when * object". The constructors recognize when an instance of InvocationProxy is
* an instance of InvocationProxy is passed in and do not create * passed in and do not create a new InvocationProxy as a wrapper. They instead
* a new InvocationProxy as a wrapper. They instead use the passed in * use the passed in InvocationProxy.
* InvocationProxy.
* *
*/ */
public class DispatchEvents extends JacobObject { public class DispatchEvents extends JacobObject {
/** /**
* pointer to an MS data struct. * pointer to an MS data struct. The COM layer knows the name of this
* The COM layer knows the name of this variable and puts the windows * variable and puts the windows memory pointer here.
* memory pointer here.
*/ */
int m_pConnPtProxy = 0; int m_pConnPtProxy = 0;
/** /**
* the wrapper for the event sink. * the wrapper for the event sink. This object is the one that will be sent
* This object is the one that will be sent a message when an event * a message when an event occurs in the MS layer. Normally, the
* occurs in the MS layer. Normally, the InvocationProxy will forward * InvocationProxy will forward the messages to a wrapped object that it
* the messages to a wrapped object that it contains. * contains.
*/ */
InvocationProxy mInvocationProxy = null; InvocationProxy mInvocationProxy = null;
/** /**
* This is the most commonly used constructor. * This is the most commonly used constructor.
* <p> * <p>
* Creates the event callback linkage between the the * Creates the event callback linkage between the the MS program represented
* MS program represented by the Dispatch object and the * by the Dispatch object and the Java object that will receive the
* Java object that will receive the callback. * callback.
* <p> * <p>
* Can be used on any object that implements IProvideClassInfo. * Can be used on any object that implements IProvideClassInfo.
* *
* @param sourceOfEvent Dispatch object who's MS app will generate callbacks * @param sourceOfEvent
* @param eventSink Java object that wants to receive the events * Dispatch object who's MS app will generate callbacks
* @param eventSink
* Java object that wants to receive the events
*/ */
public DispatchEvents(Dispatch sourceOfEvent, Object eventSink) { public DispatchEvents(Dispatch sourceOfEvent, Object eventSink) {
this(sourceOfEvent, eventSink, null); this(sourceOfEvent, eventSink, null);
@@ -76,48 +75,59 @@ public class DispatchEvents extends JacobObject {
/** /**
* None of the samples use this constructor. * None of the samples use this constructor.
* <p> * <p>
* Creates the event callback linkage between the the * Creates the event callback linkage between the the MS program represented
* MS program represented by the Dispatch object and the * by the Dispatch object and the Java object that will receive the
* Java object that will receive the callback. * callback.
* <p> * <p>
* Used when the program doesn't implement IProvideClassInfo. It provides * Used when the program doesn't implement IProvideClassInfo. It provides a
* a way to find the TypeLib in the registry based on the programId. The TypeLib * way to find the TypeLib in the registry based on the programId. The
* is looked up in the registry on the path * TypeLib is looked up in the registry on the path
* HKEY_LOCAL_MACHINE/SOFTWARE/Classes/CLSID/(CLID drived from progid)/ProgID/Typelib * HKEY_LOCAL_MACHINE/SOFTWARE/Classes/CLSID/(CLID drived from
* progid)/ProgID/Typelib
* *
* @param sourceOfEvent Dispatch object who's MS app will generate callbacks * @param sourceOfEvent
* @param eventSink Java object that wants to receive the events * Dispatch object who's MS app will generate callbacks
* @param progId program id in the registry that has a TypeLib subkey. * @param eventSink
* The progrId is mapped to a CLSID that is they used to look up the key to the Typelib * Java object that wants to receive the events
* @param progId
* program id in the registry that has a TypeLib subkey. The
* progrId is mapped to a CLSID that is they used to look up the
* key to the Typelib
*/ */
public DispatchEvents(Dispatch sourceOfEvent, Object eventSink, String progId) { public DispatchEvents(Dispatch sourceOfEvent, Object eventSink,
String progId) {
this(sourceOfEvent, eventSink, progId, null); this(sourceOfEvent, eventSink, progId, null);
} }
/** /**
* Creates the event callback linkage between the the * Creates the event callback linkage between the the MS program represented
* MS program represented by the Dispatch object and the * by the Dispatch object and the Java object that will receive the
* Java object that will receive the callback. * callback.
* <p> * <p>
* This method was added because Excel doesn't implement IProvideClassInfo * This method was added because Excel doesn't implement IProvideClassInfo
* and the registry entry for Excel.Application doesn't include a typelib key. * and the registry entry for Excel.Application doesn't include a typelib
* key.
* *
* <pre> * <pre>
* DispatchEvents de = * DispatchEvents de = new DispatchEvents(someDispatch, someEventHAndler,
* new DispatchEvents(someDispatch,someEventHAndler, * &quot;Excel.Application&quot;,
* "Excel.Application", * &quot;C:\\Program Files\\Microsoft Office\\OFFICE11\\EXCEL.EXE&quot;);
* "C:\\Program Files\\Microsoft Office\\OFFICE11\\EXCEL.EXE");
* </pre> * </pre>
* @param sourceOfEvent Dispatch object who's MS app will generate callbacks *
* @param eventSink Java object that wants to receive the events * @param sourceOfEvent
* @param progId , mandatory if the typelib is specified * Dispatch object who's MS app will generate callbacks
* @param typeLib The location of the typelib to use * @param eventSink
* Java object that wants to receive the events
* @param progId ,
* mandatory if the typelib is specified
* @param typeLib
* The location of the typelib to use
*/ */
public DispatchEvents(Dispatch sourceOfEvent, Object eventSink, String progId, String typeLib) public DispatchEvents(Dispatch sourceOfEvent, Object eventSink,
{ String progId, String typeLib) {
if (JacobObject.isDebugEnabled()) { if (JacobObject.isDebugEnabled()) {
System.out.println( System.out.println("DispatchEvents: Registering " + eventSink
"DispatchEvents: Registering "+ eventSink + "for events "); + "for events ");
} }
if (eventSink instanceof InvocationProxy) { if (eventSink instanceof InvocationProxy) {
mInvocationProxy = (InvocationProxy) eventSink; mInvocationProxy = (InvocationProxy) eventSink;
@@ -130,14 +140,18 @@ public class DispatchEvents extends JacobObject {
if (JacobObject.isDebugEnabled()) { if (JacobObject.isDebugEnabled()) {
JacobObject.debug("Cannot register null event sink for events"); JacobObject.debug("Cannot register null event sink for events");
} }
throw new IllegalArgumentException("Cannot register null event sink for events"); throw new IllegalArgumentException(
"Cannot register null event sink for events");
} }
} }
/** /**
* Returns an instance of the proxy configured with pTargetObject as its target * Returns an instance of the proxy configured with pTargetObject as its
* target
*
* @param pTargetObject * @param pTargetObject
* @return InvocationProxy an instance of the proxy this DispatchEvents will send to the COM layer * @return InvocationProxy an instance of the proxy this DispatchEvents will
* send to the COM layer
*/ */
protected InvocationProxy getInvocationProxy(Object pTargetObject) { protected InvocationProxy getInvocationProxy(Object pTargetObject) {
InvocationProxy newProxy = new InvocationProxyAllVariants(); InvocationProxy newProxy = new InvocationProxyAllVariants();
@@ -146,28 +160,34 @@ public class DispatchEvents extends JacobObject {
} }
/** /**
* hooks up a connection point proxy by progId * hooks up a connection point proxy by progId event methods on the sink
* event methods on the sink object will be called * object will be called by name with a signature of <name>(Variant[] args)
* by name with a signature of <name>(Variant[] args)
* *
* You must specify the location of the typeLib. * You must specify the location of the typeLib.
* *
* @param src dispatch that is the source of the messages * @param src
* @param sink the object that will receive the messages * dispatch that is the source of the messages
* @param progId optional program id. most folks don't need this either * @param sink
* @param typeLib optional parameter for those programs that don't register their type libs (like Excel) * the object that will receive the messages
* @param progId
* optional program id. most folks don't need this either
* @param typeLib
* optional parameter for those programs that don't register
* their type libs (like Excel)
*/ */
private native void init3(Dispatch src, Object sink, String progId, String typeLib); private native void init3(Dispatch src, Object sink, String progId,
String typeLib);
/** /**
* now private so only this object can asccess * now private so only this object can asccess was: call this to explicitly
* was: call this to explicitly release the com object before gc * release the com object before gc
* *
*/ */
private native void release(); private native void release();
/* /*
* (non-Javadoc) * (non-Javadoc)
*
* @see java.lang.Object#finalize() * @see java.lang.Object#finalize()
*/ */
protected void finalize() { protected void finalize() {
@@ -176,6 +196,7 @@ public class DispatchEvents extends JacobObject {
/* /*
* (non-Javadoc) * (non-Javadoc)
*
* @see com.jacob.com.JacobObject#safeRelease() * @see com.jacob.com.JacobObject#safeRelease()
*/ */
public void safeRelease() { public void safeRelease() {
@@ -189,7 +210,9 @@ public class DispatchEvents extends JacobObject {
m_pConnPtProxy = 0; m_pConnPtProxy = 0;
} else { } else {
// looks like a double release // looks like a double release
if (isDebugEnabled()){debug("DispatchEvents:"+this.hashCode()+" double release");} if (isDebugEnabled()) {
debug("DispatchEvents:" + this.hashCode() + " double release");
}
} }
} }

View File

@@ -0,0 +1,82 @@
/**
*
*/
package com.jacob.com;
/**
* A bunch of DispatchIds that were pulled out of the Dispatch class for version
* 1.14.
*/
public class DispatchIdentifier {
private DispatchIdentifier() {
// This is utility class so there is no constructor.
}
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;
}

View File

@@ -36,6 +36,7 @@ public class DispatchProxy extends JacobObject {
/** /**
* Marshals the passed in dispatch into the stream * Marshals the passed in dispatch into the stream
*
* @param localDispatch * @param localDispatch
*/ */
public DispatchProxy(Dispatch localDispatch) { public DispatchProxy(Dispatch localDispatch) {
@@ -55,13 +56,15 @@ public class DispatchProxy extends JacobObject {
private native Dispatch MarshalFromStream(); private native Dispatch MarshalFromStream();
/** /**
* now private so only this object can asccess * now private so only this object can access was: call this to explicitly
* was: call this to explicitly release the com object before gc * release the com object before gc
* *
*/ */
private native void release(); private native void release();
/* (non-Javadoc) /*
* (non-Javadoc)
*
* @see java.lang.Object#finalize() * @see java.lang.Object#finalize()
*/ */
public void finalize() { public void finalize() {
@@ -70,17 +73,20 @@ public class DispatchProxy extends JacobObject {
/* /*
* (non-Javadoc) * (non-Javadoc)
*
* @see com.jacob.com.JacobObject#safeRelease() * @see com.jacob.com.JacobObject#safeRelease()
*/ */
public void safeRelease() public void safeRelease() {
{
super.safeRelease(); super.safeRelease();
if (m_pStream != 0) { if (m_pStream != 0) {
release(); release();
m_pStream = 0; m_pStream = 0;
} else { } else {
// looks like a double release // looks like a double release
if (isDebugEnabled()){debug(this.getClass().getName()+":"+this.hashCode()+" double release");} if (isDebugEnabled()) {
debug(this.getClass().getName() + ":" + this.hashCode()
+ " double release");
}
} }
} }
} }

View File

@@ -23,7 +23,8 @@ package com.jacob.com;
* An implementation of IEnumVariant based on code submitted by Thomas Hallgren * An implementation of IEnumVariant based on code submitted by Thomas Hallgren
* (mailto:Thomas.Hallgren@eoncompany.com) * (mailto:Thomas.Hallgren@eoncompany.com)
*/ */
public class EnumVariant extends JacobObject implements java.util.Enumeration { public class EnumVariant extends JacobObject implements
java.util.Enumeration<Variant> {
private int m_pIEnumVARIANT; private int m_pIEnumVARIANT;
private final Variant[] m_recBuf = new Variant[1]; private final Variant[] m_recBuf = new Variant[1];
@@ -39,10 +40,8 @@ public class EnumVariant extends JacobObject implements java.util.Enumeration {
*/ */
public EnumVariant(Dispatch disp) { public EnumVariant(Dispatch disp) {
int[] hres = new int[1]; int[] hres = new int[1];
Variant evv = Dispatch.invokev(disp, Variant evv = Dispatch.invokev(disp, DispatchIdentifier.DISPID_NEWENUM,
Dispatch.DISPID_NEWENUM, Dispatch.Get, new Variant[0], hres);
Dispatch.Get,
new Variant[0], hres);
if (evv.getvt() != Variant.VariantObject) if (evv.getvt() != Variant.VariantObject)
// //
// The DISPID_NEWENUM did not result in a valid object // The DISPID_NEWENUM did not result in a valid object
@@ -56,7 +55,8 @@ public class EnumVariant extends JacobObject implements java.util.Enumeration {
/** /**
* Implements java.util.Enumeration * Implements java.util.Enumeration
* @return boolean true if there are more elements in ths enumeration *
* @return boolean true if there are more elements in this enumeration
*/ */
public boolean hasMoreElements() { public boolean hasMoreElements() {
{ {
@@ -70,10 +70,11 @@ public class EnumVariant extends JacobObject implements java.util.Enumeration {
/** /**
* Implements java.util.Enumeration * Implements java.util.Enumeration
*
* @return next element in the enumeration * @return next element in the enumeration
*/ */
public Object nextElement() { public Variant nextElement() {
Object last = m_recBuf[0]; Variant last = m_recBuf[0];
if (last == null) { if (last == null) {
if (this.Next(m_recBuf) <= 0) if (this.Next(m_recBuf) <= 0)
throw new java.util.NoSuchElementException(); throw new java.util.NoSuchElementException();
@@ -85,59 +86,71 @@ public class EnumVariant extends JacobObject implements java.util.Enumeration {
/** /**
* Get next element in collection or null if at end * Get next element in collection or null if at end
*
* @return Variant that is next in the collection * @return Variant that is next in the collection
* @deprecated use nextElement() instead
*/ */
@Deprecated
public Variant Next() { public Variant Next() {
if (hasMoreElements()) if (hasMoreElements())
return (Variant) nextElement(); return nextElement();
return null; return null;
} }
/** /**
* This should be private and wrapped to protect JNI layer.
*
* @param receiverArray * @param receiverArray
* @return don't know what the int is that is returned, help! * @return Returns the next variant object pointer as an int from windows
* layer
*/ */
public native int Next(Variant[] receiverArray); public native int Next(Variant[] receiverArray);
/** /**
* This should be private and wrapped to protect JNI layer.
*
* @param count * @param count
* number to skip
*/ */
public native void Skip(int count); public native void Skip(int count);
/** /**
* * This should be private and wrapped to protect JNI layer
*/ */
public native void Reset(); public native void Reset();
/** /**
* now private so only this object can asccess * now private so only this object can access was: call this to explicitly
* was: call this to explicitly release the com object before gc * release the com object before gc
* *
*/ */
private native void release(); private native void release();
/* /*
* (non-Javadoc) * (non-Javadoc)
*
* @see java.lang.Object#finalize() * @see java.lang.Object#finalize()
*/ */
protected void finalize() protected void finalize() {
{
safeRelease(); safeRelease();
} }
/* /*
* (non-Javadoc) * (non-Javadoc)
*
* @see com.jacob.com.JacobObject#safeRelease() * @see com.jacob.com.JacobObject#safeRelease()
*/ */
public void safeRelease() public void safeRelease() {
{
super.safeRelease(); super.safeRelease();
if (m_pIEnumVARIANT != 0) { if (m_pIEnumVARIANT != 0) {
this.release(); this.release();
m_pIEnumVARIANT = 0; m_pIEnumVARIANT = 0;
} else { } else {
// looks like a double release // looks like a double release
if (isDebugEnabled()){debug(this.getClass().getName()+":"+this.hashCode()+" double release");} if (isDebugEnabled()) {
debug(this.getClass().getName() + ":" + this.hashCode()
+ " double release");
}
} }
} }
} }

View File

@@ -23,19 +23,18 @@ package com.jacob.com;
* @version $Id$ * @version $Id$
* @author joe * @author joe
* *
* DispatchEvents wraps this class around any event handlers * DispatchEvents wraps this class around any event handlers before making the
* before making the JNI call that sets up the link with EventProxy. * JNI call that sets up the link with EventProxy. This means that
* This means that EventProxy.cpp just calls invoke(String,Variant[]) * EventProxy.cpp just calls invoke(String,Variant[]) against the instance of
* against the instance of this class. Then this class does * this class. Then this class does reflection against the event listener to
* reflection against the event listener to call the actual event methods. * call the actual event methods. The event methods can return void or return a
* The event methods can return void or return a Variant. Any * Variant. Any value returned will be passed back to the calling windows module
* value returned will be passed back to the calling windows module
* by the Jacob JNI layer. * by the Jacob JNI layer.
* <p> * <p>
* *
* The void returning signature is the standard legacy signature. * The void returning signature is the standard legacy signature. The Variant
* The Variant returning signature was added in 1.10 to support event handlers * returning signature was added in 1.10 to support event handlers returning
* returning values. * values.
* *
*/ */
public abstract class InvocationProxy { public abstract class InvocationProxy {
@@ -46,29 +45,35 @@ public abstract class InvocationProxy {
protected Object mTargetObject = null; protected Object mTargetObject = null;
/** /**
* dummy constructor for subclasses that don't actually wrap * dummy constructor for subclasses that don't actually wrap anything and
* anything and just want to override the invoke() method * just want to override the invoke() method
*/ */
protected InvocationProxy() { protected InvocationProxy() {
super(); super();
} }
/** /**
* The method actually invoked by EventProxy.cpp. * The method actually invoked by EventProxy.cpp. The method name is
* The method name is calculated by the underlying JNI code from the MS windows * calculated by the underlying JNI code from the MS windows Callback
* Callback function name. The method is assumed to take an array of Variant * function name. The method is assumed to take an array of Variant objects.
* objects. The method may return a Variant or be a void. Those are the only * The method may return a Variant or be a void. Those are the only two
* two options that will not blow up. * options that will not blow up.
* <p> * <p>
* Subclasses that override this should make sure mTargetObject is not null before processing. * Subclasses that override this should make sure mTargetObject is not null
* before processing.
* *
* @param methodName name of method in mTargetObject we will invoke * @param methodName
* @param targetParameters Variant[] that is the single parameter to the method * name of method in mTargetObject we will invoke
* @param targetParameters
* Variant[] that is the single parameter to the method
* @return an object that will be returned to the com event caller
*/ */
public abstract Variant invoke(String methodName, Variant targetParameters[]); public abstract Variant invoke(String methodName,
Variant targetParameters[]);
/** /**
* used by EventProxy.cpp to create variant objects in the right thread * used by EventProxy.cpp to create variant objects in the right thread
*
* @return Variant object that will be used by the COM layer * @return Variant object that will be used by the COM layer
*/ */
public Variant getVariant() { public Variant getVariant() {
@@ -77,20 +82,22 @@ public abstract class InvocationProxy {
/** /**
* Sets the target for this InvocationProxy. * Sets the target for this InvocationProxy.
*
* @param pTargetObject * @param pTargetObject
* @throws IllegalArgumentException if target is not publicly accessable * @throws IllegalArgumentException
* if target is not publicly accessible
*/ */
public void setTarget(Object pTargetObject) { public void setTarget(Object pTargetObject) {
if (JacobObject.isDebugEnabled()) { if (JacobObject.isDebugEnabled()) {
JacobObject.debug( JacobObject.debug("InvocationProxy: setting target "
"InvocationProxy: setting target "+pTargetObject); + pTargetObject);
} }
if (pTargetObject != null) { if (pTargetObject != null) {
// JNI code apparently bypasses this check and could operate against // JNI code apparently bypasses this check and could operate against
// protected classes. This seems like a security issue... // protected classes. This seems like a security issue...
// maybe it was because JNI code isn't in a package? // maybe it was because JNI code isn't in a package?
if (!java.lang.reflect.Modifier.isPublic( if (!java.lang.reflect.Modifier.isPublic(pTargetObject.getClass()
pTargetObject.getClass().getModifiers())){ .getModifiers())) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"InvocationProxy only public classes can receive event notifications"); "InvocationProxy only public classes can receive event notifications");
} }

View File

@@ -24,62 +24,69 @@ import java.lang.reflect.Method;
/** /**
* This class acts as a proxy between the windows event callback mechanism and * This class acts as a proxy between the windows event callback mechanism and
* the Java classes that are looking for events. It assumes that * the Java classes that are looking for events. It assumes that all of the Java
* all of the Java classes that are looking for events implement methods with the * classes that are looking for events implement methods with the same names as
* same names as the windows events and that the implemented methods accept an * the windows events and that the implemented methods accept an array of
* array of variant objects. The methods can return void or a Variant that * variant objects. The methods can return void or a Variant that will be
* will be returned to the calling layer. All Event methods that will be * returned to the calling layer. All Event methods that will be recognized by
* recognized by InvocationProxyAllEvents have the signature * InvocationProxyAllEvents have the signature
* *
* <code> void eventMethodName(Variant[])</code> * <code> void eventMethodName(Variant[])</code> or
* or
* <code> Variant eventMethodName(Variant[])</code> * <code> Variant eventMethodName(Variant[])</code>
*/ */
public class InvocationProxyAllVariants extends InvocationProxy { public class InvocationProxyAllVariants extends InvocationProxy {
/* /*
* (non-Javadoc) * (non-Javadoc)
* @see com.jacob.com.InvocationProxy#invoke(java.lang.String, com.jacob.com.Variant[]) *
* @see com.jacob.com.InvocationProxy#invoke(java.lang.String,
* com.jacob.com.Variant[])
*/ */
@SuppressWarnings("unchecked")
public Variant invoke(String methodName, Variant targetParameters[]) { public Variant invoke(String methodName, Variant targetParameters[]) {
Variant mVariantToBeReturned = null; Variant mVariantToBeReturned = null;
if (mTargetObject == null) { if (mTargetObject == null) {
if (JacobObject.isDebugEnabled()) { if (JacobObject.isDebugEnabled()) {
JacobObject.debug( JacobObject.debug("InvocationProxy: received notification ("
"InvocationProxy: received notification ("+methodName+") with no target set"); + methodName + ") with no target set");
} }
// structured programming guidlines say this return should not be up here // structured programming guidlines say this return should not be up
// here
return null; return null;
} }
Class targetClass = mTargetObject.getClass(); Class targetClass = mTargetObject.getClass();
if (methodName == null) { if (methodName == null) {
throw new IllegalArgumentException("InvocationProxy: missing method name"); throw new IllegalArgumentException(
"InvocationProxy: missing method name");
} }
if (targetParameters == null) { if (targetParameters == null) {
throw new IllegalArgumentException("InvocationProxy: missing Variant parameters"); throw new IllegalArgumentException(
"InvocationProxy: missing Variant parameters");
} }
try { try {
if (JacobObject.isDebugEnabled()) { if (JacobObject.isDebugEnabled()) {
JacobObject.debug("InvocationProxy: trying to invoke "+methodName JacobObject.debug("InvocationProxy: trying to invoke "
+" on "+mTargetObject); + methodName + " on " + mTargetObject);
} }
Method targetMethod; Method targetMethod;
targetMethod = targetClass.getMethod(methodName, targetMethod = targetClass.getMethod(methodName,
new Class[] { Variant[].class }); new Class[] { Variant[].class });
if (targetMethod != null) { if (targetMethod != null) {
// protected classes can't be invoked against even if they // protected classes can't be invoked against even if they
// let you grab the method. you could do targetMethod.setAccessible(true); // let you grab the method. you could do
// targetMethod.setAccessible(true);
// but that should be stopped by the security manager // but that should be stopped by the security manager
Object mReturnedByInvocation = null; Object mReturnedByInvocation = null;
mReturnedByInvocation = mReturnedByInvocation = targetMethod.invoke(mTargetObject,
targetMethod.invoke(mTargetObject,new Object[] {targetParameters}); new Object[] { targetParameters });
if (mReturnedByInvocation == null) { if (mReturnedByInvocation == null) {
mVariantToBeReturned = null; mVariantToBeReturned = null;
} else if (!(mReturnedByInvocation instanceof Variant)) { } else if (!(mReturnedByInvocation instanceof Variant)) {
// could try and convert to Variant here. // could try and convert to Variant here.
throw new IllegalArgumentException( throw new IllegalArgumentException(
"InvocationProxy: invokation of target method returned " "InvocationProxy: invokation of target method returned "
+"non-null non-variant object: "+mReturnedByInvocation); + "non-null non-variant object: "
+ mReturnedByInvocation);
} else { } else {
mVariantToBeReturned = (Variant) mReturnedByInvocation; mVariantToBeReturned = (Variant) mReturnedByInvocation;
} }
@@ -88,10 +95,11 @@ public class InvocationProxyAllVariants extends InvocationProxy {
// what causes this exception? // what causes this exception?
e.printStackTrace(); e.printStackTrace();
} catch (NoSuchMethodException e) { } catch (NoSuchMethodException e) {
// this happens whenever the listener doesn't implement all the methods // this happens whenever the listener doesn't implement all the
// methods
if (JacobObject.isDebugEnabled()) { if (JacobObject.isDebugEnabled()) {
JacobObject.debug("InvocationProxy: listener ("+mTargetObject+") doesn't implement " JacobObject.debug("InvocationProxy: listener (" + mTargetObject
+ methodName); + ") doesn't implement " + methodName);
} }
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
e.printStackTrace(); e.printStackTrace();
@@ -100,7 +108,8 @@ public class InvocationProxyAllVariants extends InvocationProxy {
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
// can't access the method on the target instance for some reason // can't access the method on the target instance for some reason
if (JacobObject.isDebugEnabled()) { if (JacobObject.isDebugEnabled()) {
JacobObject.debug("InvocationProxy: probably tried to access public method on non public class" JacobObject
.debug("InvocationProxy: probably tried to access public method on non public class"
+ methodName); + methodName);
} }
e.printStackTrace(); e.printStackTrace();

View File

@@ -20,9 +20,9 @@
package com.jacob.com; package com.jacob.com;
/** /**
* The parent class of all Jacob exceptions. * The parent class of all Jacob exceptions. They all used to be based off of
* They all used to be based off of RuntimeException or ComException * RuntimeException or ComException but it was decided to base them all off of
* but it was decided to base them all off of one owned by this project. * one owned by this project.
*/ */
public class JacobException extends RuntimeException { public class JacobException extends RuntimeException {
@@ -32,8 +32,7 @@ public class JacobException extends RuntimeException {
private static final long serialVersionUID = -1637125318746002715L; private static final long serialVersionUID = -1637125318746002715L;
/** /**
* Default constructor. * Default constructor. Calls super with a "No Message Provided" string
* Calls super with a "No Message Provided" string
*/ */
public JacobException() { public JacobException() {
super("No Message Provided"); super("No Message Provided");
@@ -41,6 +40,7 @@ public class JacobException extends RuntimeException {
/** /**
* standard constructor * standard constructor
*
* @param message * @param message
*/ */
public JacobException(String message) { public JacobException(String message) {

View File

@@ -19,17 +19,13 @@
*/ */
package com.jacob.com; package com.jacob.com;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
/** /**
* The superclass of all Jacob objects. It is used to * The superclass of all Jacob objects. It is used to create a standard API
* create a standard API framework and to facillitate memory management * framework and to facilitate memory management for Java and COM memory
* for Java and COM memory elements. * elements.
* <p> * <p>
* All instances of this class and subclasses are automatically manged * All instances of this class and subclasses are automatically managed by the
* by the ROT. This means the ROT cannot be a subclass of JacobObject. * ROT. This means the ROT cannot be a subclass of JacobObject.
* <p> * <p>
* All COM object created by JACOB extend this class so that we can * 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 * automatically release them when the thread is detached from COM - if we leave
@@ -39,77 +35,17 @@ import java.util.Properties;
public class JacobObject { public class JacobObject {
/** /**
* holds the build version as retrieved from the version.properties * Standard constructor that adds this JacobObject to the memory management
* file that exists in the JAR. * pool.
* This can be retrived by calling the static method getBuildVersion()
* @see getBuildVersion()
*/
private static String buildVersion = "";
/**
* holds the build date as retrieved from the version.properties
* file that exists in the JAR
* This can be retrived by calling the static method getBuildDate()
* @see getBuildDate()
*/
private static String buildDate = "";
/**
* Standard constructor that adds this JacobObject
* to the memory management pool.
*/ */
public JacobObject() { public JacobObject() {
ROT.addObject(this); ROT.addObject(this);
} }
/** /**
* Loads version information from version.properties that was * Finalizers call this method. This method should release any COM data
* built as part of this release. * structures in a way that it can be called multiple times. This can happen
* * if someone manually calls this and then a finalizer calls it.
*/
private static void loadVersionProperties(){
Properties versionProps = new Properties();
// can't use system class loader cause won't work in jws
InputStream stream =
JacobObject.class.getClassLoader().getResourceAsStream("version.properties");
try {
versionProps.load(stream);
stream.close();
buildVersion = (String)versionProps.get("version");
buildDate = (String)versionProps.get("build.date");
} catch (IOException ioe){
System.out.println("blah, couldn't load props");
}
}
/**
* loads version.properties and returns the value of versin in it
* @return String value of version in version.properties or "" if none
*/
public static String getBuildDate(){
if (buildDate.equals("")){
loadVersionProperties();
}
return buildDate;
}
/**
* loads version.properties and returns the value of versin in it
* @return String value of version in version.properties or "" if none
*/
public static String getBuildVersion(){
if (buildVersion.equals("")){
loadVersionProperties();
}
return buildVersion;
}
/**
* Finalizers call this method.
* This method should release any COM data structures in a way
* that it can be called multiple times.
* This can happen if someone manually calls this and then
* a finalizer calls it.
*/ */
public void safeRelease() { public void safeRelease() {
// currently does nothing - subclasses may do something // currently does nothing - subclasses may do something
@@ -120,7 +56,7 @@ public class JacobObject {
} }
/** /**
* When things go wrong, it is usefull to be able to debug the ROT. * When things go wrong, it is useful to be able to debug the ROT.
*/ */
private static final boolean DEBUG = private static final boolean DEBUG =
// true; // true;
@@ -130,16 +66,38 @@ public class JacobObject {
// return true; // return true;
return DEBUG; return DEBUG;
} }
/** /**
* Very basic debugging fucntion. * Loads JacobVersion.Properties and returns the value of version in it
*
* @deprecated use JacobReleaseInfo.getBuildDate() instead.
* @return String value of version in JacobVersion.Properties or "" if none
*/
@Deprecated
public static String getBuildDate() {
return JacobReleaseInfo.getBuildDate();
}
/**
* Loads JacobVersion.Properties and returns the value of version in it
*
* @deprecated use JacobReleaseInfo.getBuildVersion() instead.
* @return String value of version in JacobVersion.Properties or "" if none
*/
@Deprecated
public static String getBuildVersion() {
return JacobReleaseInfo.getBuildVersion();
}
/**
* Very basic debugging function.
*
* @param istrMessage * @param istrMessage
*/ */
protected static void debug(String istrMessage) protected static void debug(String istrMessage) {
{ if (isDebugEnabled()) {
if(isDebugEnabled()) System.out.println(istrMessage + " in thread "
{ + Thread.currentThread().getName());
System.out.println(istrMessage
+ " in thread "+ Thread.currentThread().getName());
} }
} }
@@ -150,5 +108,4 @@ public class JacobObject {
LibraryLoader.loadJacobLibrary(); LibraryLoader.loadJacobLibrary();
} }
} }

View File

@@ -0,0 +1,96 @@
package com.jacob.com;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
/**
* An interface to the version properties file. This code was removed from
* JacobObject because it doesn't belong there.
*
*/
public class JacobReleaseInfo {
/**
* holds the build version as retrieved from the version properties file
* that exists in the JAR. This can be retrieved by calling the static
* method getBuildVersion()
*
* @see #getBuildVersion()
*/
private static String buildVersion = "";
/**
* holds the build date as retrieved from the version properties file that
* exists in the JAR This can be retrieved by calling the static method
* getBuildDate()
*
* @see #getBuildDate()
*/
private static String buildDate = "";
/** the name of the jacob version properties file */
private static final String PROPERTY_FILE_NAME = "META-INF/JacobVersion.properties";
/**
* Loads version information from PROPERTY_FILE_NAME that was built as part
* of this release.
*
* @throws IllegalStateException
* when it can't find the version properties file
*/
private static void loadVersionProperties() {
Properties versionProps = new Properties();
// can't use system class loader cause won't work in JavaWebStart
InputStream stream = JacobReleaseInfo.class.getClassLoader()
.getResourceAsStream(PROPERTY_FILE_NAME);
// This should never happen. This is an attempt to make something work
// for WebSphere. They may be using some kind of Servlet loader that
// needs an absolute path based search
if (stream == null) {
stream = JacobReleaseInfo.class.getClassLoader()
.getResourceAsStream("/" + PROPERTY_FILE_NAME);
}
// A report came in that WebSphere had trouble finding the file
// so lets trap it. Plus, it's a good idea anyway.
if (stream == null) {
throw new IllegalStateException(
"Can't find "
+ PROPERTY_FILE_NAME
+ " using JacobReleaseInfo.class.getClassLoader().getResourceAsStream()");
} else {
try {
versionProps.load(stream);
stream.close();
buildVersion = (String) versionProps.get("version");
buildDate = (String) versionProps.get("build.date");
} catch (IOException ioe) {
ioe.printStackTrace();
System.err.println("Warning! Couldn't load props " + ioe);
}
}
}
/**
* loads PROPERT_FILE_NAME and returns the value of version in it
*
* @return String value of version in PROPERT_FILE_NAME or "" if none
*/
public static String getBuildDate() {
if (buildDate.equals("")) {
loadVersionProperties();
}
return buildDate;
}
/**
* loads PROPERT_FILE_NAME and returns the value of version in it
*
* @return String value of version in PROPERT_FILE_NAME or "" if none
*/
public static String getBuildVersion() {
if (buildVersion.equals("")) {
loadVersionProperties();
}
return buildVersion;
}
}

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999-2004 Sourceforge JACOB Project. * Copyright (c) 1999-2007 Sourceforge JACOB Project.
* All rights reserved. Originator: Dan Adler (http://danadler.com). * All rights reserved. Originator: Dan Adler (http://danadler.com).
* Get more information about JACOB at http://sourceforge.net/projects/jacob-project * Get more information about JACOB at http://sourceforge.net/projects/jacob-project
* *
@@ -19,44 +19,208 @@
*/ */
package com.jacob.com; package com.jacob.com;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.Set;
/** /**
* Utility class to centralize the way in which the jacob JNI library is loaded. * Utility class to centralize the way in which the jacob JNI library is loaded.
* <p>
* *
* <p>If system property {@link #JACOB_DLL_PATH} is defined, the file located there * This supports defining the path or library name using system properties or a
* will be loaded as the jacob dll. If the system property is not defined, normal * custom resource file. If desired, jacob can auto-detect the correct version
* library paths will be used to load the jacob dll. This means it defaults to the * of the DLL for 32 or 64 bit windows, as long as you have named them
* previous behavior for existing applications. * differently.
*
* <ol>
* <li> If system property {@link #JACOB_DLL_PATH} is defined, the file located
* there will be loaded as the jacob dll using System.load(). </li>
*
* <li> If system property {@link #JACOB_DLL_NAME} is defined, the file located
* there will be loaded as the jacob dll. </li>
* <li> If system property {@link #JACOB_DLL_NAME_X86} and
* {@link #JACOB_DLL_NAME_X64} are defined, the file located there will be
* loaded as the jacob dll, depending on the version of Windows. </li>
*
* <li> If {@link #JACOB_DLL_NAME} is defined in the
* {@code com.jacob.com.JacobLibraryLoader} resource file, the specified dll
* will be loaded from the {@code java.library.path}. </li>
* <li> If {@link #JACOB_DLL_NAME_X86} and {@link #JACOB_DLL_NAME_X64} are
* defined in the {@code com.jacob.com.JacobLibraryLoader} resource file, the
* specified dll will be loaded from the {@code java.library.path}, depending
* on the version of Windows. </li>
*
* <li> If none of the above are true, the default is to load the library named
* "jacob-&lt;version&gt;-&lt;arch&gt" (or
* "jacob-&lt;version&gt;-&lt;arch&rt;.dll") from the {@code java.library.path}.
* </li>
* </ol>
*
* The standard behavior for most applications is that {@code LoadLibrary()}
* will be called to load the dll. {@code LoadLibary()} searches directories
* specified in the variable {@code java.library.path}. This is why most test
* cases specify -Djava.library.path in their command line arguments.
* <p> * <p>
* The standard behavior for most applications is that LoadLibrary() will be called * JACOB_DLL_PATH submitted sourceforge ticket 1493647 Added 1.11 <br>
* to load the dll. LoadLibary searches directories specified in the variable * JACOB_DLL_NAME, JACOB_DLL_NAME_32, JACOB_DLL_NAME_64 submitted sourceforge
* java.library.path . This is why most test cases specify -Djava.library.path in * ticket 1845039 Added 1.14M7
* their command line arguments *
* <p>
* Submitted sourceforge ticket 1493647
* @author Scott Dickerson (sjd78) * @author Scott Dickerson (sjd78)
* @author Jason Smith
*/ */
public final class LibraryLoader { public final class LibraryLoader {
/** /**
* Name of system property (currently <tt>jacob.dll.path</tt>) that may contain * Name of system property (currently <tt>jacob.dll.path</tt>) that may
* an absolute path to the JNI library. * contain an absolute path to the JNI library.
*/ */
public static final String JACOB_DLL_PATH = "jacob.dll.path"; public static final String JACOB_DLL_PATH = "jacob.dll.path";
/**
* Name of system property (currently <tt>jacob.dll.name</tt>) that may
* contain an alternate name for the JNI library (default is 'jacob').
*/
public static final String JACOB_DLL_NAME = "jacob.dll.name";
/** /**
* Load the jacob dll either from an absolute path defined in system property * Name of system property (currently <tt>jacob.dll.name</tt>) that may
* {@link #JACOB_DLL_PATH} or as a general library called "<tt>jacob</tt>". * contain an alternate name for the JNI library (default is 'jacob'), 32
* @throws UnsatisfiedLinkError if the library does not exist. * bit windows.
*/
public static final String JACOB_DLL_NAME_X86 = "jacob.dll.name.x86";
/**
* Name of system property (currently <tt>jacob.dll.name</tt>) that may
* contain an alternate name for the JNI library (default is 'jacob'), 64
* bit windows.
*/
public static final String JACOB_DLL_NAME_X64 = "jacob.dll.name.x64";
/**
* Appended to "jacob" when building DLL name This string must EXACTLY match
* the string in the build.xml file
*/
public static final String DLL_NAME_MODIFIER_32_BIT = "x86";
/**
* Appended to "jacob" when building DLL name This string must EXACTLY match
* the string in the build.xml file
*/
public static final String DLL_NAME_MODIFIER_64_BIT = "x64";
/**
* Load the jacob dll either from an absolute path or by a library name,
* both of which may be defined in various ways.
*
* @throws UnsatisfiedLinkError
* if the library does not exist.
*/ */
public static void loadJacobLibrary() { public static void loadJacobLibrary() {
// In some cases, a library that uses Jacob won't be able to set system
// properties
// prior to Jacob being loaded. The resource bundle provides an
// alternate way to
// override DLL name or path that will be loaded with Jacob regardless
// of other
// initialization order.
ResourceBundle resources = null;
Set<String> keys = new HashSet<String>();
try {
resources = ResourceBundle.getBundle(LibraryLoader.class.getName(),
Locale.getDefault(), LibraryLoader.class.getClassLoader());
for (Enumeration<String> i = resources.getKeys(); i
.hasMoreElements();) {
String key = i.nextElement();
keys.add(key);
}
} catch (MissingResourceException e) {
// Do nothing. Expected.
}
// First, check for a defined PATH. System property overrides resource
// bundle.
String path = System.getProperty(JACOB_DLL_PATH); String path = System.getProperty(JACOB_DLL_PATH);
if (path == null && resources != null && keys.contains(JACOB_DLL_PATH)) {
path = (String) resources.getObject(JACOB_DLL_PATH);
}
if (path != null) { if (path != null) {
System.load(path); System.load(path);
} else {
// Path was not defined, so use the OS mechanism for loading
// libraries.
// Check for a defined NAME. System property overrides resource
// bundle.
String name = null;
if (System.getProperty(JACOB_DLL_NAME) != null) {
name = System.getProperty(JACOB_DLL_NAME);
} else if (System.getProperty(JACOB_DLL_NAME_X86) != null
&& shouldLoad32Bit()) {
name = System.getProperty(JACOB_DLL_NAME_X86);
} else if (System.getProperty(JACOB_DLL_NAME_X64) != null
&& !shouldLoad32Bit()) {
name = System.getProperty(JACOB_DLL_NAME_X64);
} else if (resources != null && keys.contains(JACOB_DLL_NAME)) {
name = resources.getString(JACOB_DLL_NAME);
} else if (resources != null && keys.contains(JACOB_DLL_NAME_X86)
&& shouldLoad32Bit()) {
name = resources.getString(JACOB_DLL_NAME_X86);
} else if (resources != null && keys.contains(JACOB_DLL_NAME_X64)
&& !shouldLoad32Bit()) {
name = resources.getString(JACOB_DLL_NAME_X64);
} else {
// No alternate NAME or PATH was defined, so use the default.
// We will almost always end up here.
name = getPreferredDLLName();
} }
else {
System.loadLibrary("jacob"); // System.out.println("Loading " + name);
System.loadLibrary(name);
} }
} }
/**
* Developer note: This method MUST be synchronized with the DLL names
* created as part of the build process in build.xml
* <p>
* The DLL name is "jacob\<PLATFORM\>.release"
*
* @return the preferred name of the DLL adjusted for this platform and
* version without the ".dll" extension
*/
public static String getPreferredDLLName() {
if (shouldLoad32Bit()) {
return "jacob" + "-" + JacobReleaseInfo.getBuildVersion() + "-"
+ DLL_NAME_MODIFIER_32_BIT;
} else {
return "jacob" + "-" + JacobReleaseInfo.getBuildVersion() + "- "
+ DLL_NAME_MODIFIER_64_BIT;
}
}
/**
* Detects whether this is a 32-bit JVM.
*
* @return {@code true} if this is a 32-bit JVM.
*/
protected static boolean shouldLoad32Bit() {
// This guesses whether we are running 32 or 64 bit Java.
// This works for Sun and IBM JVMs version 5.0 or later.
// May need to be adjusted for non-Sun JVMs.
String bits = System.getProperty("sun.arch.data.model", "?");
if (bits.equals("32"))
return true;
else if (bits.equals("64"))
return false;
// this works for jRocket
String arch = System.getProperty("java.vm.name", "?");
if (arch.toLowerCase().indexOf("64-bit") >= 0)
return false;
return true;
}
} // LibraryLoader } // LibraryLoader

View File

@@ -20,10 +20,10 @@
package com.jacob.com; package com.jacob.com;
/** /**
* We provide our own main sta thread to avoid COM tagging a random * We provide our own main sta thread to avoid COM tagging a random thread as
* thread as the main STA - this is the thread in which all Apartment * the main STA - this is the thread in which all Apartment threaded components
* threaded components will be created if the client chooses an MTA * will be created if the client chooses an MTA threading model for the java
* threading model for the java side of the app. * side of the app.
*/ */
public class MainSTA extends STA { public class MainSTA extends STA {
} }

View File

@@ -20,10 +20,9 @@
package com.jacob.com; package com.jacob.com;
/** /**
* Thrown by java APIs that are not implemented either because * Thrown by java APIs that are not implemented either because they were never
* they were never implemented or because they are bieng deprecated * implemented or because they are being deprecated This is a subclass of
* This is a subclass of ComException so callers can still just catch * ComException so callers can still just catch ComException.
* ComException.
*/ */
public class NotImplementedException extends JacobException { public class NotImplementedException extends JacobException {
@@ -39,5 +38,4 @@ public class NotImplementedException extends JacobException {
super(description); super(description);
} }
} }

View File

@@ -30,61 +30,64 @@ import java.util.WeakHashMap;
* current thread so all the methods are static and they implicitly get the * current thread so all the methods are static and they implicitly get the
* current thread. * current thread.
* <p> * <p>
* The clearObjects method is used to release all the COM objects created by Jacob * The clearObjects method is used to release all the COM objects created by
* in the current thread prior to uninitializing COM for that thread. * Jacob in the current thread prior to uninitializing COM for that thread.
* <p> * <p>
* Prior to 1.9, manual garbage collection was the only option in Jacob, but * Prior to 1.9, manual garbage collection was the only option in Jacob, but
* from 1.9 onward, setting the com.jacob.autogc system property * from 1.9 onward, setting the com.jacob.autogc system property allows the
* allows the objects referenced by the ROT to be automatically GCed. * objects referenced by the ROT to be automatically GCed. Automatic GC may be
* Automatic GC may be preferable in systems with heavy event callbacks. * preferable in systems with heavy event callbacks.
* <p> * <p>
* Is [ 1116101 ] jacob-msg 0284 relevant??? * Is [ 1116101 ] jacob-msg 0284 relevant???
*/ */
public abstract class ROT { public abstract class ROT {
/** /**
* Manual garbage collection was the only option pre 1.9 * Manual garbage collection was the only option pre 1.9 Can staticly cache
* Can staticly cache the results because only one value * the results because only one value and we don't let it change during a
* and we don't let it change during a run * run
*/ */
protected static final boolean USE_AUTOMATIC_GARBAGE_COLLECTION = protected static final boolean USE_AUTOMATIC_GARBAGE_COLLECTION = "true"
"true".equalsIgnoreCase( System.getProperty( "com.jacob.autogc" ) ); .equalsIgnoreCase(System.getProperty("com.jacob.autogc"));
/** /**
* Suffix added to class name to make up property name that determines if this * Suffix added to class name to make up property name that determines if
* object should be stored in the ROT. This 1.13 "feature" makes it possible * this object should be stored in the ROT. This 1.13 "feature" makes it
* to cause VariantViaEvent objects to not be added to the ROT in event callbacks. * possible to cause VariantViaEvent objects to not be added to the ROT in
* event callbacks.
* <p> * <p>
* We don't have a static for the actual property because there is a different property * We don't have a static for the actual property because there is a
* for each class that may make use of this feature. * different property for each class that may make use of this feature.
*/ */
protected static String PUT_IN_ROT_SUFFIX = ".PutInROT"; protected static String PUT_IN_ROT_SUFFIX = ".PutInROT";
/** /**
* A hash table where each element is another * A hash table where each element is another HashMap that represents a
* HashMap that represents a thread. * thread. Each thread HashMap contains the com objects created in that
* Each thread HashMap contains the com objects created * thread
* in that thread
*/ */
private static HashMap rot = new HashMap(); private static HashMap<String, Map<JacobObject, String>> rot = new HashMap<String, Map<JacobObject, String>>();
/** /**
* adds a new thread storage area to rot * adds a new thread storage area to rot
*
* @return Map corresponding to the thread that this call was made in * @return Map corresponding to the thread that this call was made in
*/ */
protected synchronized static Map addThread() { protected synchronized static Map<JacobObject, String> addThread() {
// should use the id here instead of the name because the name can be changed // should use the id here instead of the name because the name can be
// changed
String t_name = Thread.currentThread().getName(); String t_name = Thread.currentThread().getName();
if (rot.containsKey(t_name)) { if (rot.containsKey(t_name)) {
// nothing to do // nothing to do
} else { } else {
Map tab = null; Map<JacobObject, String> tab = null;
if (JacobObject.isDebugEnabled()) { if (JacobObject.isDebugEnabled()) {
JacobObject.debug( "ROT: Automatic GC flag == " + USE_AUTOMATIC_GARBAGE_COLLECTION ); JacobObject.debug("ROT: Automatic GC flag == "
+ USE_AUTOMATIC_GARBAGE_COLLECTION);
} }
if (!USE_AUTOMATIC_GARBAGE_COLLECTION) { if (!USE_AUTOMATIC_GARBAGE_COLLECTION) {
tab = new HashMap(); tab = new HashMap<JacobObject, String>();
} else { } else {
tab = new WeakHashMap(); tab = new WeakHashMap<JacobObject, String>();
} }
rot.put(t_name, tab); rot.put(t_name, tab);
} }
@@ -92,59 +95,68 @@ public abstract class ROT {
} }
/** /**
* returns the pool for this thread if it exists. can create a new * returns the pool for this thread if it exists. can create a new one if
* one if you wish by passing in TRUE * you wish by passing in TRUE
*
* @param createIfDoesNotExist * @param createIfDoesNotExist
* @return Map the collection that holds the objects created in the current thread * @return Map the collection that holds the objects created in the current
* thread
*/ */
protected synchronized static Map getThreadObjects( boolean createIfDoesNotExist ) { protected synchronized static Map<JacobObject, String> getThreadObjects(
boolean createIfDoesNotExist) {
String t_name = Thread.currentThread().getName(); String t_name = Thread.currentThread().getName();
if (!rot.containsKey(t_name) && createIfDoesNotExist) { if (!rot.containsKey(t_name) && createIfDoesNotExist) {
addThread(); addThread();
} }
return (Map) rot.get( t_name ); return rot.get(t_name);
} }
/** /**
* Iterates across all of the entries in the Hashmap in the rot * Iterates across all of the entries in the Hashmap in the rot that
* that corresponds to this thread. * corresponds to this thread. This calls safeRelease() on each entry and
* This calls safeRelease() on each entry and then * then clears the map when done and removes it from the rot. All traces of
* clears the map when done and removes it from the rot. * this thread's objects will disapear. This is called by COMThread in the
* All traces of this thread's objects will disapear. * tear down and provides a synchronous way of releasing memory
* This is called by COMThread in the tear down and provides a
* synchronous way of releasing memory
*/ */
protected synchronized static void clearObjects() { protected synchronized static void clearObjects() {
Map tab = getThreadObjects( false ); Map<JacobObject, String> tab = getThreadObjects(false);
if (JacobObject.isDebugEnabled()) { if (JacobObject.isDebugEnabled()) {
JacobObject.debug( "ROT: " + rot.keySet().size() + " thread tables exist" ); JacobObject.debug("ROT: " + rot.keySet().size()
+ " thread tables exist");
} }
if (tab != null) { if (tab != null) {
if (JacobObject.isDebugEnabled()) { if (JacobObject.isDebugEnabled()) {
JacobObject.debug( "ROT: " + tab.keySet().size() + " objects to clear in this thread " ); JacobObject.debug("ROT: " + tab.keySet().size()
+ " objects to clear in this thread ");
} }
// walk the values // walk the values
Iterator it = tab.keySet().iterator(); Iterator<JacobObject> it = tab.keySet().iterator();
while (it.hasNext()) { while (it.hasNext()) {
JacobObject o = (JacobObject) it.next(); JacobObject o = it.next();
if (o != null if (o != null
// can't use this cause creates a Variant if calling SafeAray // can't use this cause creates a Variant if calling SafeAray
// and we get an exceptin modifying the collection while iterating // and we get an exception modifying the collection while
// iterating
// && o.toString() != null // && o.toString() != null
) { ) {
if (JacobObject.isDebugEnabled()) { if (JacobObject.isDebugEnabled()) {
if (o instanceof SafeArray) { if (o instanceof SafeArray) {
// SafeArray create more objects when calling toString() // SafeArray create more objects when calling
// which causes a concurrent modification exception in HashMap // toString()
JacobObject.debug( "ROT: removing " + o.getClass().getName() ); // which causes a concurrent modification exception
// in HashMap
JacobObject.debug("ROT: removing "
+ o.getClass().getName());
} else { } else {
// Variant toString() is probably always bad in here // Variant toString() is probably always bad in here
JacobObject.debug( "ROT: removing " + o.hashCode() + "->" + o.getClass().getName() ); JacobObject.debug("ROT: removing " + o.hashCode()
+ "->" + o.getClass().getName());
} }
} }
o.safeRelease(); o.safeRelease();
} }
// used to be an iterator.remove() but why bother when we're nuking them all anyway? // used to be an iterator.remove() but why bother when we're
// nuking them all anyway?
} }
// empty the collection // empty the collection
tab.clear(); tab.clear();
@@ -161,16 +173,18 @@ public abstract class ROT {
} }
/** /**
* @deprecated the java model leave the responsibility of clearing up objects * @deprecated the java model leave the responsibility of clearing up
* to the Garbage Collector. Our programming model should not require that the * objects to the Garbage Collector. Our programming model
* user specifically remove object from the thread. * should not require that the user specifically remove object
* from the thread.
* *
* This will remove an object from the ROT * This will remove an object from the ROT
* @param o * @param o
*/ */
@Deprecated
protected synchronized static void removeObject(JacobObject o) { protected synchronized static void removeObject(JacobObject o) {
String t_name = Thread.currentThread().getName(); String t_name = Thread.currentThread().getName();
Map tab = (Map) rot.get( t_name ); Map<JacobObject, String> tab = rot.get(t_name);
if (tab != null) { if (tab != null) {
tab.remove(o); tab.remove(o);
} }
@@ -179,19 +193,22 @@ public abstract class ROT {
/** /**
* adds an object to the HashMap for the current thread * adds an object to the HashMap for the current thread
*
* @param o * @param o
*/ */
protected synchronized static void addObject(JacobObject o) { protected synchronized static void addObject(JacobObject o) {
// check the system property to see if this class is put in the ROT // check the system property to see if this class is put in the ROT
// the default value is "true" which simulates the old behavior // the default value is "true" which simulates the old behavior
String shouldIncludeClassInROT = String shouldIncludeClassInROT = System.getProperty(o.getClass()
System.getProperty(o.getClass().getName() + PUT_IN_ROT_SUFFIX,"true"); .getName()
+ PUT_IN_ROT_SUFFIX, "true");
if (shouldIncludeClassInROT.equalsIgnoreCase("false")) { if (shouldIncludeClassInROT.equalsIgnoreCase("false")) {
if (JacobObject.isDebugEnabled()) { if (JacobObject.isDebugEnabled()) {
JacobObject.debug("JacobObject: New instance of "+o.getClass().getName()+" not added to ROT"); JacobObject.debug("JacobObject: New instance of "
+ o.getClass().getName() + " not added to ROT");
} }
} else { } else {
Map tab = getThreadObjects( false ); Map<JacobObject, String> tab = getThreadObjects(false);
if (tab == null) { if (tab == null) {
// this thread has not been initialized as a COM thread // this thread has not been initialized as a COM thread
// so make it part of MTA for backwards compatibility // so make it part of MTA for backwards compatibility
@@ -199,9 +216,9 @@ public abstract class ROT {
tab = getThreadObjects(true); tab = getThreadObjects(true);
} }
if (JacobObject.isDebugEnabled()) { if (JacobObject.isDebugEnabled()) {
JacobObject.debug( JacobObject.debug("ROT: adding " + o + "->"
"ROT: adding " + o + "->" + o.getClass().getName() + + o.getClass().getName()
" table size prior to addition:" + tab.size() ); + " table size prior to addition:" + tab.size());
} }
if (tab != null) { if (tab != null) {
tab.put(o, null); tab.put(o, null);
@@ -210,12 +227,11 @@ public abstract class ROT {
} }
/** /**
* ROT can't be a subclass of JacobObject because of the way ROT pools are managed * ROT can't be a subclass of JacobObject because of the way ROT pools are
* so we force a DLL load here by referncing JacobObject * managed so we force a DLL load here by referencing JacobObject
*/ */
static { static {
LibraryLoader.loadJacobLibrary(); LibraryLoader.loadJacobLibrary();
} }
} }

View File

@@ -37,7 +37,9 @@ public class STA extends Thread {
start(); // start the thread start(); // start the thread
} }
/* (non-Javadoc) /*
* (non-Javadoc)
*
* @see java.lang.Thread#run() * @see java.lang.Thread#run()
*/ */
public void run() { public void run() {
@@ -57,6 +59,7 @@ public class STA extends Thread {
* Override this method to create and initialize any COM component that you * Override this method to create and initialize any COM component that you
* want to run in this thread. If anything fails, return false to terminate * want to run in this thread. If anything fails, return false to terminate
* the thread. * the thread.
*
* @return always returns true * @return always returns true
*/ */
public boolean OnInit() { public boolean OnInit() {
@@ -89,8 +92,8 @@ public class STA extends Thread {
public native void quitMessagePump(); public native void quitMessagePump();
/** /**
* STA isn't a subclass of JacobObject so a reference to it doesn't load * STA isn't a subclass of JacobObject so a reference to it doesn't load the
* the DLL without this * DLL without this
*/ */
static { static {
LibraryLoader.loadJacobLibrary(); LibraryLoader.loadJacobLibrary();

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,471 @@
/**
*
*/
package com.jacob.com;
import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
import java.util.Date;
/**
* A utility class used to convert between Java objects and Variants
*/
public final class VariantUtilities {
private VariantUtilities() {
// utility class with only static methods don't need constructors
}
/**
* Populates a variant object from a java object. This method attempts to
* figure out the appropriate Variant type
*
* @param targetVariant
* @param pValueObject
* @param fByRef
*/
protected static void populateVariant(Variant targetVariant,
Object pValueObject, boolean fByRef) {
if (pValueObject == null) {
targetVariant.putEmpty();
} else if (pValueObject instanceof Integer) {
if (fByRef) {
targetVariant.putIntRef(((Integer) pValueObject).intValue());
} else {
targetVariant.putInt(((Integer) pValueObject).intValue());
}
} else if (pValueObject instanceof Short) {
if (fByRef) {
targetVariant.putShortRef(((Short) pValueObject).shortValue());
} else {
targetVariant.putShort(((Short) pValueObject).shortValue());
}
} else if (pValueObject instanceof String) {
if (fByRef) {
targetVariant.putStringRef((String) pValueObject);
} else {
targetVariant.putString((String) pValueObject);
}
} else if (pValueObject instanceof Boolean) {
if (fByRef) {
targetVariant.putBooleanRef(((Boolean) pValueObject)
.booleanValue());
} else {
targetVariant.putBoolean(((Boolean) pValueObject)
.booleanValue());
}
} else if (pValueObject instanceof Double) {
if (fByRef) {
targetVariant.putDoubleRef(((Double) pValueObject)
.doubleValue());
} else {
targetVariant.putDouble(((Double) pValueObject).doubleValue());
}
} else if (pValueObject instanceof Float) {
if (fByRef) {
targetVariant.putFloatRef(((Float) pValueObject).floatValue());
} else {
targetVariant.putFloat(((Float) pValueObject).floatValue());
}
} else if (pValueObject instanceof BigDecimal) {
if (fByRef) {
targetVariant.putDecimalRef(((BigDecimal) pValueObject));
} else {
targetVariant.putDecimal(((BigDecimal) pValueObject));
}
} else if (pValueObject instanceof Byte) {
if (fByRef) {
targetVariant.putByteRef(((Byte) pValueObject).byteValue());
} else {
targetVariant.putByte(((Byte) pValueObject).byteValue());
}
} else if (pValueObject instanceof Date) {
if (fByRef) {
targetVariant.putDateRef((Date) pValueObject);
} else {
targetVariant.putDate((Date) pValueObject);
}
} else if (pValueObject instanceof Long) {
if (fByRef) {
targetVariant.putLongRef(((Long) pValueObject).longValue());
} else {
targetVariant.putLong(((Long) pValueObject).longValue());
}
} else if (pValueObject instanceof Currency) {
if (fByRef) {
targetVariant.putCurrencyRef(((Currency) pValueObject));
} else {
targetVariant.putCurrency(((Currency) pValueObject));
}
} else if (pValueObject instanceof SafeArray) {
if (fByRef) {
targetVariant.putSafeArrayRef((SafeArray) pValueObject);
} else {
targetVariant.putSafeArray((SafeArray) pValueObject);
}
} else if (pValueObject instanceof Dispatch) {
if (fByRef) {
targetVariant.putDispatchRef((Dispatch) pValueObject);
} else {
targetVariant.putDispatch((Dispatch) pValueObject);
}
} else if (pValueObject instanceof Variant) {
// newly added 1.12-pre6 to support VT_VARIANT
targetVariant.putVariant(pValueObject);
} else {
// should really throw an illegal argument exception if its an
// invalid type
if (fByRef) {
targetVariant.putObjectRef(pValueObject);
} else {
targetVariant.putObject(pValueObject);
}
}
}
/**
* Map arguments based on msdn documentation. This method relies on the
* variant constructor except for arrays.
*
* @param objectToBeMadeIntoVariant
* @return Variant that represents the object
*/
@SuppressWarnings("unchecked")
protected static Variant objectToVariant(Object objectToBeMadeIntoVariant) {
if (objectToBeMadeIntoVariant == null) {
return new Variant();
} else if (objectToBeMadeIntoVariant instanceof Variant) {
// if a variant was passed in then be a slacker and just return it
return (Variant) objectToBeMadeIntoVariant;
} else if (objectToBeMadeIntoVariant.getClass().isArray()) {
// automatically convert arrays using reflection
SafeArray sa = null;
int len1 = Array.getLength(objectToBeMadeIntoVariant);
Object first = Array.get(objectToBeMadeIntoVariant, 0);
if (first.getClass().isArray()) {
int max = 0;
for (int i = 0; i < len1; i++) {
Object e1 = Array.get(objectToBeMadeIntoVariant, 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(objectToBeMadeIntoVariant, i);
for (int j = 0; j < Array.getLength(e1); j++) {
sa.setVariant(i, j, objectToVariant(Array.get(e1, j)));
}
}
} else {
sa = new SafeArray(Variant.VariantVariant, len1);
for (int i = 0; i < len1; i++) {
sa.setVariant(i, objectToVariant(Array.get(
objectToBeMadeIntoVariant, i)));
}
}
Variant returnVariant = new Variant();
populateVariant(returnVariant, sa, false);
return returnVariant;
} else {
// rely on populateVariant to throw an exception if its an
// invalid type
Variant returnVariant = new Variant();
populateVariant(returnVariant, objectToBeMadeIntoVariant, false);
return returnVariant;
}
}
/**
* converts an array of objects into an array of Variants by repeatedly
* calling obj2Variant(Object)
*
* @param arrayOfObjectsToBeConverted
* @return Variant[]
*/
protected static Variant[] objectsToVariants(
Object[] arrayOfObjectsToBeConverted) {
Variant vArg[] = new Variant[arrayOfObjectsToBeConverted.length];
for (int i = 0; i < arrayOfObjectsToBeConverted.length; i++) {
vArg[i] = objectToVariant(arrayOfObjectsToBeConverted[i]);
}
return vArg;
}
/**
* Convert a JACOB Variant value to a Java object (type conversions).
* provided in Sourceforge feature request 959381. A fix was done to handle
* byRef bug report 1607878.
* <p>
* Unlike other toXXX() methods, it does not do a type conversion except for
* special data types (it shouldn't do any!)
* <p>
* Converts Variant.VariantArray types to SafeArrays
*
* @return Corresponding Java object of the type matching the Variant type.
* @throws IllegalStateException
* if no underlying windows data structure
* @throws NotImplementedException
* if unsupported conversion is requested
* @throws JacobException
* if the calculated result was a JacobObject usually as a
* result of error
*/
protected static Object variantToObject(Variant sourceData) {
Object result = null;
short type = sourceData.getvt(); // variant type
if ((type & Variant.VariantArray) == Variant.VariantArray) { // array
// returned?
SafeArray array = null;
type = (short) (type - Variant.VariantArray);
// From SF Bug 1840487
// This did call toSafeArray(false) but that meant
// this was the only variantToObject() that didn't have its own
// copy of the data so you would end up with weird run time
// errors after some GC. So now we just get stupid about it and
// always make a copy just like toSafeArray() does.
array = sourceData.toSafeArray();
result = array;
} else { // non-array object returned
switch (type) {
case Variant.VariantEmpty: // 0
case Variant.VariantNull: // 1
break;
case Variant.VariantShort: // 2
result = new Short(sourceData.getShort());
break;
case Variant.VariantShort | Variant.VariantByref: // 2
result = new Short(sourceData.getShortRef());
break;
case Variant.VariantInt: // 3
result = new Integer(sourceData.getInt());
break;
case Variant.VariantInt | Variant.VariantByref: // 3
result = new Integer(sourceData.getIntRef());
break;
case Variant.VariantFloat: // 4
result = new Float(sourceData.getFloat());
break;
case Variant.VariantFloat | Variant.VariantByref: // 4
result = new Float(sourceData.getFloatRef());
break;
case Variant.VariantDouble: // 5
result = new Double(sourceData.getDouble());
break;
case Variant.VariantDouble | Variant.VariantByref: // 5
result = new Double(sourceData.getDoubleRef());
break;
case Variant.VariantCurrency: // 6
result = sourceData.getCurrency();
break;
case Variant.VariantCurrency | Variant.VariantByref: // 6
result = sourceData.getCurrencyRef();
break;
case Variant.VariantDate: // 7
result = sourceData.getJavaDate();
break;
case Variant.VariantDate | Variant.VariantByref: // 7
result = sourceData.getJavaDateRef();
break;
case Variant.VariantString: // 8
result = sourceData.getString();
break;
case Variant.VariantString | Variant.VariantByref: // 8
result = sourceData.getStringRef();
break;
case Variant.VariantDispatch: // 9
result = sourceData.getDispatch();
break;
case Variant.VariantDispatch | Variant.VariantByref: // 9
result = sourceData.getDispatchRef(); // Can dispatches even
// be byRef?
break;
case Variant.VariantError: // 10
result = new NotImplementedException(
"toJavaObject() Not implemented for VariantError");
break;
case Variant.VariantBoolean: // 11
result = new Boolean(sourceData.getBoolean());
break;
case Variant.VariantBoolean | Variant.VariantByref: // 11
result = new Boolean(sourceData.getBooleanRef());
break;
case Variant.VariantVariant: // 12 they are always by ref
result = new NotImplementedException(
"toJavaObject() Not implemented for VariantVariant without ByRef");
break;
case Variant.VariantVariant | Variant.VariantByref: // 12
result = sourceData.getVariant();
break;
case Variant.VariantObject: // 13
result = new NotImplementedException(
"toJavaObject() Not implemented for VariantObject");
break;
case Variant.VariantDecimal: // 14
result = sourceData.getDecimal();
break;
case Variant.VariantDecimal | Variant.VariantByref: // 14
result = sourceData.getDecimalRef();
break;
case Variant.VariantByte: // 17
result = new Byte(sourceData.getByte());
break;
case Variant.VariantByte | Variant.VariantByref: // 17
result = new Byte(sourceData.getByteRef());
break;
case Variant.VariantLongInt: // 20
result = new Long(sourceData.getLong());
break;
case Variant.VariantLongInt | Variant.VariantByref: // 20
result = new Long(sourceData.getLongRef());
break;
case Variant.VariantTypeMask: // 4095
result = new NotImplementedException(
"toJavaObject() Not implemented for VariantTypeMask");
break;
case Variant.VariantArray: // 8192
result = new NotImplementedException(
"toJavaObject() Not implemented for VariantArray");
break;
case Variant.VariantByref: // 16384
result = new NotImplementedException(
"toJavaObject() Not implemented for VariantByref");
break;
default:
result = new NotImplementedException("Unknown return type: "
+ type);
// there was a "return result" here that caused defect 1602118
// so it was removed
break;
}// switch (type)
if (result instanceof JacobException) {
throw (JacobException) result;
}
}
return result;
}// toJava()
/**
* Verifies that we have a scale 0 <= x <= 28 and now more than 96 bits of
* data. The roundToMSDecimal method will attempt to adjust a BigDecimal to
* pass this set of tests
*
* @param in
* @throws IllegalArgumentException
* if out of bounds
*/
protected static void validateDecimalScaleAndBits(BigDecimal in) {
BigInteger allWordBigInt = in.unscaledValue();
if (in.scale() > 28) {
// should this cast to a string and call putStringRef()?
throw new IllegalArgumentException(
"VT_DECIMAL only supports a maximum scale of 28 and the passed"
+ " in value has a scale of " + in.scale());
} else if (in.scale() < 0) {
// should this cast to a string and call putStringRef()?
throw new IllegalArgumentException(
"VT_DECIMAL only supports a minimum scale of 0 and the passed"
+ " in value has a scale of " + in.scale());
} else if (allWordBigInt.bitLength() > 12 * 8) {
throw new IllegalArgumentException(
"VT_DECIMAL supports a maximum of "
+ 12
* 8
+ " bits not counting scale and the number passed in has "
+ allWordBigInt.bitLength());
} else {
// no bounds problem to be handled
}
}
/**
* Largest possible number with scale set to 0
*/
private static final BigDecimal LARGEST_DECIMAL = new BigDecimal(
new BigInteger("ffffffffffffffffffffffff", 16));
/**
* Smallest possible number with scale set to 0. MS doesn't support negative
* scales like BigDecimal.
*/
private static final BigDecimal SMALLEST_DECIMAL = new BigDecimal(
new BigInteger("ffffffffffffffffffffffff", 16).negate());
/**
* Does any validation that couldn't have been fixed by rounding or scale
* modification.
*
* @param in
* The BigDecimal to be validated
* @throws IllegalArgumentException
* if the number is too large or too small or null
*/
protected static void validateDecimalMinMax(BigDecimal in) {
if (in == null) {
throw new IllegalArgumentException(
"null is not a supported Decimal value.");
} else if (LARGEST_DECIMAL.compareTo(in) < 0) {
throw new IllegalArgumentException(
"Value too large for VT_DECIMAL data type:" + in.toString()
+ " integer: " + in.toBigInteger().toString(16)
+ " scale: " + in.scale());
} else if (SMALLEST_DECIMAL.compareTo(in) > 0) {
throw new IllegalArgumentException(
"Value too small for VT_DECIMAL data type:" + in.toString()
+ " integer: " + in.toBigInteger().toString(16)
+ " scale: " + in.scale());
}
}
/**
* Rounds the scale and bit length so that it will pass
* validateDecimalScaleBits(). Developers should call this method if they
* really want MS Decimal and don't want to lose precision.
* <p>
* Changing the scale on a number that can fit in an MS Decimal can change
* the number's representation enough that it will round to a number too
* large to be represented by an MS VT_DECIMAL
*
* @param sourceDecimal
* @return BigDecimal a new big decimal that was rounded to fit in an MS
* VT_DECIMAL
*/
public static BigDecimal roundToMSDecimal(BigDecimal sourceDecimal) {
BigInteger sourceDecimalIntComponent = sourceDecimal.unscaledValue();
BigDecimal destinationDecimal = new BigDecimal(
sourceDecimalIntComponent, sourceDecimal.scale());
int roundingModel = BigDecimal.ROUND_HALF_UP;
validateDecimalMinMax(destinationDecimal);
// First limit the number of digits and then the precision.
// Try and round to 29 digits because we can sometimes do that
BigInteger allWordBigInt;
allWordBigInt = destinationDecimal.unscaledValue();
if (allWordBigInt.bitLength() > 96) {
destinationDecimal = destinationDecimal.round(new MathContext(29));
// see if 29 digits uses more than 96 bits
if (allWordBigInt.bitLength() > 96) {
// Dang. It was over 97 bits so shorten it one more digit to
// stay <= 96 bits
destinationDecimal = destinationDecimal.round(new MathContext(
28));
}
}
// the bit manipulations above may change the scale so do it afterwards
// round the scale to the max MS can support
if (destinationDecimal.scale() > 28) {
destinationDecimal = destinationDecimal.setScale(28, roundingModel);
}
if (destinationDecimal.scale() < 0) {
destinationDecimal = destinationDecimal.setScale(0, roundingModel);
}
return destinationDecimal;
}
}

View File

@@ -20,14 +20,15 @@
package com.jacob.com; package com.jacob.com;
/** /**
* a public class to variant that is used * a public class to variant that is used to track which variant objects are
* to track which variant objects are created by event callbacks * created by event callbacks This is solely used for that purpose.
* This is soley used for that purpose.
*/ */
public class VariantViaEvent extends Variant { public class VariantViaEvent extends Variant {
/**
* Standard constructor used by JNI event handling layer
*/
public VariantViaEvent() { public VariantViaEvent() {
super(); super();
} }
} }

View File

@@ -38,6 +38,7 @@ public class WrongThreadException extends JacobException {
/** /**
* standard constructor with a string message * standard constructor with a string message
*
* @param s * @param s
*/ */
public WrongThreadException(String s) { public WrongThreadException(String s) {

View File

@@ -4,34 +4,87 @@ import com.jacob.activeX.ActiveXComponent;
import com.jacob.test.BaseTestCase; import com.jacob.test.BaseTestCase;
/** /**
* This exercises the two Dispatch factor methods that let you * This exercises the two Dispatch factor methods that let you control whether
* control whether you create a new running COM object or connect to an existing one * you create a new running COM object or connect to an existing one
* <p> * <p>
* May need to run with some command line options (including from inside Eclipse). * May need to run with some command line options (including from inside
* Look in the docs area at the Jacob usage document for command line options. * Eclipse). Look in the docs area at the Jacob usage document for command line
* options.
*/ */
public class ActiveXComponentFactoryTest extends BaseTestCase { public class ActiveXComponentFactoryTest extends BaseTestCase {
/**
* This test is supposed to verify we get multiple instances when we mean
* too. Unfortunately, it requires that the runner of the test verify via
* the "Windows Task Manager"
*/
public void testMultipleInstances() {
ComThread.InitMTA();
String mApplicationId = "Word.Application";
ActiveXComponent instance1 = ActiveXComponent
.createNewInstance(mApplicationId);
ActiveXComponent instance2 = ActiveXComponent
.createNewInstance(mApplicationId);
try {
Thread.sleep(10000);
} catch (InterruptedException ie) {
}
instance1.invoke("Quit", new Variant[] {});
instance2.invoke("Quit", new Variant[] {});
ComThread.Release();
}
/**
* This test is supposed to verify we can force multiple items through a
* single running instance. It requires that a user physically watch the
* "Windows Task Manager" to verify only one copy of MS Word is executing
*/
public void testOnlyOneInstance() {
ComThread.InitMTA();
String mApplicationId = "Word.Application";
ActiveXComponent instance1 = new ActiveXComponent(mApplicationId);
ActiveXComponent instance2 = ActiveXComponent
.connectToActiveInstance(mApplicationId);
assertNotNull(instance2);
try {
Thread.sleep(10000);
} catch (InterruptedException ie) {
}
instance1.invoke("Quit", new Variant[] {});
ComThread.Release();
}
/**
* Test that verifies function of the ActiveXComponentFactory
*/
public void testActiveXComponentFactory() { public void testActiveXComponentFactory() {
ComThread.InitSTA(true); ComThread.InitSTA(true);
try { try {
System.out.println("This test only works if MS Word is NOT already running"); System.out
.println("This test only works if MS Word is NOT already running");
String mApplicationId = "Word.Application"; String mApplicationId = "Word.Application";
ActiveXComponent mTryConnectingFirst = ActiveXComponent.connectToActiveInstance(mApplicationId); ActiveXComponent mTryConnectingFirst = ActiveXComponent
.connectToActiveInstance(mApplicationId);
if (mTryConnectingFirst != null) { if (mTryConnectingFirst != null) {
mTryConnectingFirst.invoke("Quit", new Variant[] {}); mTryConnectingFirst.invoke("Quit", new Variant[] {});
System.out.println("Was able to connect to MSWord when hadn't started it"); System.out
.println("Was able to connect to MSWord when hadn't started it");
} else { } else {
System.out.println("Correctly could not connect to running MSWord"); System.out
.println("Correctly could not connect to running MSWord");
} }
System.out.println(" Word Starting"); System.out.println(" Word Starting");
ActiveXComponent mTryStartingSecond = ActiveXComponent.createNewInstance(mApplicationId); ActiveXComponent mTryStartingSecond = ActiveXComponent
.createNewInstance(mApplicationId);
if (mTryStartingSecond == null) { if (mTryStartingSecond == null) {
System.out.println("was unable to start up MSWord "); System.out.println("was unable to start up MSWord ");
} else { } else {
System.out.println("Correctly could start MSWord"); System.out.println("Correctly could start MSWord");
} }
ActiveXComponent mTryConnectingThird = ActiveXComponent.connectToActiveInstance(mApplicationId); ActiveXComponent mTryConnectingThird = ActiveXComponent
.connectToActiveInstance(mApplicationId);
if (mTryConnectingThird == null) { if (mTryConnectingThird == null) {
fail("Was unable able to connect to MSWord after previous startup"); fail("Was unable able to connect to MSWord after previous startup");
} else { } else {
@@ -40,19 +93,22 @@ public class ActiveXComponentFactoryTest extends BaseTestCase {
mTryConnectingThird.invoke("Quit", new Variant[] {}); mTryConnectingThird.invoke("Quit", new Variant[] {});
} }
Thread.sleep(2000); Thread.sleep(2000);
ActiveXComponent mTryConnectingFourth = ActiveXComponent.connectToActiveInstance(mApplicationId); ActiveXComponent mTryConnectingFourth = ActiveXComponent
.connectToActiveInstance(mApplicationId);
if (mTryConnectingFourth != null) { if (mTryConnectingFourth != null) {
mTryConnectingFourth.invoke("Quit", new Variant[] {}); mTryConnectingFourth.invoke("Quit", new Variant[] {});
fail("Was able to connect to MSWord that was stopped"); fail("Was able to connect to MSWord that was stopped");
} else { } else {
System.out.println("Correctly could not connect to running MSWord"); System.out
.println("Correctly could not connect to running MSWord");
} }
} catch (InterruptedException ie) { } catch (InterruptedException ie) {
} catch (ComException e) { } catch (ComException e) {
e.printStackTrace(); e.printStackTrace();
fail("Caught COM exception"); fail("Caught COM exception");
} finally { } finally {
//System.out.println("About to sleep for 2 seconds so we can bask in the glory of this success"); // System.out.println("About to sleep for 2 seconds so we can bask
// in the glory of this success");
// Thread.sleep(2000); // Thread.sleep(2000);
ComThread.Release(); ComThread.Release();
ComThread.quitMainSTA(); ComThread.quitMainSTA();

View File

@@ -9,29 +9,38 @@ import junit.framework.TestCase;
/** /**
* test cases that should exercise the new date conversion code * test cases that should exercise the new date conversion code
* <p> * <p>
* This test does not require any command line options because it is only a utility test * This test does not require any command line options because it is only a
* utility test
*/ */
public class DateUtilitiesTest extends TestCase { public class DateUtilitiesTest extends TestCase {
/**
* verify date conversion to and from java
*/
public void testDateUtilities() { public void testDateUtilities() {
Date now = new Date(); Date now = new Date();
double comTimeForNow = DateUtilities.convertDateToWindowsTime(now); double comTimeForNow = DateUtilities.convertDateToWindowsTime(now);
Date retrievedNow = DateUtilities.convertWindowsTimeToDate(comTimeForNow); Date retrievedNow = DateUtilities
.convertWindowsTimeToDate(comTimeForNow);
if (!now.equals(retrievedNow)) { if (!now.equals(retrievedNow)) {
fail("DateUtilities Date Test failed " +now+ " != " +retrievedNow ); fail("DateUtilities Date Test failed " + now + " != "
+ retrievedNow);
} else { } else {
System.out.println("DateUtilities Date Test passed"); System.out.println("DateUtilities Date Test passed");
} }
} }
/**
* Verify that the start of time is when we think it is.
*/
public void testBeginningOfWindowsTime() { public void testBeginningOfWindowsTime() {
// this is a magic time in the windows world // this is a magic time in the windows world
Date beginningOfWindowsTime = Date beginningOfWindowsTime = new GregorianCalendar(1899,
new GregorianCalendar(1899, Calendar.DECEMBER, 30).getTime(); Calendar.DECEMBER, 30).getTime();
double comTimeForBeginningOfWindowsTime = double comTimeForBeginningOfWindowsTime = DateUtilities
DateUtilities.convertDateToWindowsTime(beginningOfWindowsTime); .convertDateToWindowsTime(beginningOfWindowsTime);
if (comTimeForBeginningOfWindowsTime > 0) { if (comTimeForBeginningOfWindowsTime > 0) {
fail("Beginning of windows time test failed " fail("Beginning of windows time test failed "
+ comTimeForBeginningOfWindowsTime); + comTimeForBeginningOfWindowsTime);
@@ -41,5 +50,4 @@ public class DateUtilitiesTest extends TestCase {
} }
} }

View File

@@ -3,31 +3,35 @@ package com.jacob.com;
import com.jacob.test.BaseTestCase; import com.jacob.test.BaseTestCase;
/** /**
* This test verifies that the Dispatch object protects itself when * This test verifies that the Dispatch object protects itself when the
* the constructor is called with a null program id. * constructor is called with a null program id. Prior to this protection, the
* Prior to this protection, the VM might crash.m * VM might crash.m
* <p> * <p>
* May need to run with some command line options (including from inside Eclipse). * May need to run with some command line options (including from inside
* Look in the docs area at the Jacob usage document for command line options. * Eclipse). Look in the docs area at the Jacob usage document for command line
* options.
*/ */
public class DispatchNullProgramId extends BaseTestCase { public class DispatchNullProgramId extends BaseTestCase {
/**
* Verify that dispatch constructors are protected from null program ids.
*/
public void testNullProgramId() { public void testNullProgramId() {
try { try {
String nullParam = null; String nullParam = null;
new Dispatch(nullParam); new Dispatch(nullParam);
fail("the dispatch failed to protect itself from null program ids"); fail("the dispatch failed to protect itself from null program ids");
} catch (IllegalArgumentException iae) { } catch (IllegalArgumentException iae) {
System.out.println( System.out
"the dispatch protected itself from null program ids"); .println("the dispatch protected itself from null program ids");
} }
try { try {
String nullParam = ""; String nullParam = "";
new Dispatch(nullParam); new Dispatch(nullParam);
fail("the dispatch failed to protect itself from empty string program ids"); fail("the dispatch failed to protect itself from empty string program ids");
} catch (IllegalArgumentException iae) { } catch (IllegalArgumentException iae) {
System.out.println( System.out
"the dispatch protected itself from empty string program ids"); .println("the dispatch protected itself from empty string program ids");
} }
} }
} }

View File

@@ -1,24 +1,20 @@
package com.jacob.com; package com.jacob.com;
import java.util.Date;
import com.jacob.test.BaseTestCase; import com.jacob.test.BaseTestCase;
/** /**
* Test some of the Dispatch utility methods * Test some of the Dispatch utility methods
* <p> * <p>
* May need to run with some command line options (including from inside Eclipse). * May need to run with some command line options (including from inside
* Look in the docs area at the Jacob usage document for command line options. * Eclipse). Look in the docs area at the Jacob usage document for command line
* options.
*/ */
public class DispatchTest extends BaseTestCase { public class DispatchTest extends BaseTestCase {
/**
* Dummy test until someone gets their act together
*/
public void testDispatch() { public void testDispatch() {
Date testDate = new Date(); // what should we test
Variant fromDate = Dispatch.obj2variant(testDate);
Date returnedDate = fromDate.getJavaDate();
//System.out.println("test date is "+testDate);
//System.out.println("VariantDate is "+fromDate.getJavaDate());
assertTrue("Could not call obj2variant(Date) and get it to work",
testDate.equals(returnedDate));
} }
} }

View File

@@ -5,19 +5,30 @@ import com.jacob.test.BaseTestCase;
/** /**
* Test armoring of dispatch static methods * Test armoring of dispatch static methods
* <p> * <p>
* May need to run with some command line options (including from inside Eclipse). * May need to run with some command line options (including from inside
* Look in the docs area at the Jacob usage document for command line options. * Eclipse). Look in the docs area at the Jacob usage document for command line
* options.
*/ */
public class DispatchValidDispatchTest extends BaseTestCase { public class DispatchValidDispatchTest extends BaseTestCase {
/**
* force an IllegalArgumentException to verify the utility method throws
* correctly.
*/
public void testThrowIllegalArgumentException() { public void testThrowIllegalArgumentException() {
try { try {
Dispatch.call(null, 0); Dispatch.call(null, 0);
fail("Failed to throw IllegalArgumentException"); fail("Failed to throw IllegalArgumentException");
} catch (IllegalArgumentException iae) { } catch (IllegalArgumentException iae) {
System.out.println("Caught correct IllegalArgumentException: "+iae); System.out.println("Caught correct IllegalArgumentException: "
+ iae);
} }
} }
/**
* force an IllegalStateException to verify the utility method throws
* correctly.
*/
public void testThrowIllegalStateException() { public void testThrowIllegalStateException() {
try { try {
Dispatch foo = new Dispatch(); Dispatch foo = new Dispatch();

View File

@@ -5,16 +5,18 @@ import com.jacob.test.BaseTestCase;
/** /**
* This will eventually be changed to a unit test. * This will eventually be changed to a unit test.
* <p> * <p>
* May need to run with some command line options (including from inside Eclipse). * May need to run with some command line options (including from inside
* Look in the docs area at the Jacob usage document for command line options. * Eclipse). Look in the docs area at the Jacob usage document for command line
* options.
*/ */
public class JacobObjectTest extends BaseTestCase { public class JacobObjectTest extends BaseTestCase {
/**
* verify the build version and date functions work correctly
*/
public void testBuildVersion() { public void testBuildVersion() {
System.out.println("build version is "+JacobObject.getBuildVersion()); System.out.println("build version is " + JacobReleaseInfo.getBuildVersion());
System.out.println("build date is "+JacobObject.getBuildDate()); System.out.println("build date is " + JacobReleaseInfo.getBuildDate());
} }
} }

View File

@@ -0,0 +1,79 @@
package com.jacob.com;
import junit.framework.TestCase;
/**
* Tests Library loader architecture methods This test requires that jacob.jar
* be compiled and added to the classpath. You will need to refresh the release
* directory so that eclipse knows about jacob.jar. Otherwise you will get a
* "jar not found" dialog.
*
* <p>
* May need to run with some command line options (including from inside
* Eclipse). Look in the docs area at the Jacob usage document for command line
* options.
*
* @author clay_shooter
*
*/
public class LibraryLoaderTest extends TestCase {
/**
* verify the architecture switches work
*/
public void testArchitectureVersions() {
System.out.println("running on 32Bit? VM"
+ LibraryLoader.shouldLoad32Bit());
// verify no null pointer is thrown
LibraryLoader.shouldLoad32Bit();
}
/**
* verify LibraryLoader.JACOB_DLL_NAME is read by LibraryLoader
*/
public void testJacobDllNameSystemProperty() {
// fill with bad dll name
System.setProperty(LibraryLoader.JACOB_DLL_NAME, "xxx");
try {
LibraryLoader.loadJacobLibrary();
fail("Should have been unable to load dll with name xxx");
} catch (UnsatisfiedLinkError ule) {
// yes, this is what we want to see when using a bad name
}
// no way to clear a system property once set so lets try setting to
// default
System.setProperty(LibraryLoader.JACOB_DLL_NAME, LibraryLoader
.getPreferredDLLName());
try {
LibraryLoader.loadJacobLibrary();
} catch (UnsatisfiedLinkError ule) {
fail("Should have been able to load dll after setting "
+ LibraryLoader.JACOB_DLL_NAME + " to "
+ LibraryLoader.getPreferredDLLName() + " "
+ ule.getMessage());
}
}
/**
* Verifies that we get a preferred DLL name with X86 since we really only
* run the unit tests on 32 bit platforms.
*/
public void testDLLNameContainsProcessorAndVersion() {
System.out.println(LibraryLoader.getPreferredDLLName());
if (LibraryLoader.shouldLoad32Bit()) {
// we build the package and run the unit tests on X86
assertTrue(LibraryLoader.getPreferredDLLName()
+ "should have contained "
+ LibraryLoader.DLL_NAME_MODIFIER_32_BIT, LibraryLoader
.getPreferredDLLName().contains(
LibraryLoader.DLL_NAME_MODIFIER_32_BIT));
} else {
// we build the package and run the unit tests on X86
assertTrue(LibraryLoader.getPreferredDLLName()
+ "should have contained "
+ LibraryLoader.DLL_NAME_MODIFIER_64_BIT, LibraryLoader
.getPreferredDLLName().contains(
LibraryLoader.DLL_NAME_MODIFIER_64_BIT));
}
}
}

View File

@@ -14,6 +14,9 @@ import com.jacob.test.BaseTestCase;
*/ */
public class ROT2Test extends BaseTestCase { public class ROT2Test extends BaseTestCase {
/**
* runs a multi-threaded test
*/
public void testDoesNotBlowUp() { public void testDoesNotBlowUp() {
ROT2TestThread threads[] = new ROT2TestThread[4]; ROT2TestThread threads[] = new ROT2TestThread[4];
for (int i = 0; i < threads.length; i++) { for (int i = 0; i < threads.length; i++) {
@@ -29,12 +32,14 @@ public class ROT2Test extends BaseTestCase {
*/ */
public class ROT2TestThread extends Thread { public class ROT2TestThread extends Thread {
private java.util.List ThreadObjects; private java.util.List<Variant> ThreadObjects;
private int initialRunSize = 0; private int initialRunSize = 0;
/** /**
* @param arg0 * @param arg0
* @param iStartCount
* the initial number of threads
*/ */
public ROT2TestThread(String arg0, int iStartCount) { public ROT2TestThread(String arg0, int iStartCount) {
super(arg0); super(arg0);
@@ -43,7 +48,7 @@ public class ROT2Test extends BaseTestCase {
} }
/** /**
* A semi-complexe serie of steps to put the ROT under stress. 1) * A semi-complex series of steps to put the ROT under stress. 1)
* discard half the objects we've created 2) if size is greater than 1 * discard half the objects we've created 2) if size is greater than 1
* but not a even number, add 1 new object 3) stop when size is 1. * but not a even number, add 1 new object 3) stop when size is 1.
* *
@@ -54,7 +59,7 @@ public class ROT2Test extends BaseTestCase {
// so the gc can't collect them // so the gc can't collect them
// we need to create these in the thread so they end up in the right // we need to create these in the thread so they end up in the right
// ROT table // ROT table
ThreadObjects = new java.util.ArrayList(initialRunSize); ThreadObjects = new java.util.ArrayList<Variant>(initialRunSize);
for (int i = 0; i < initialRunSize; i++) { for (int i = 0; i < initialRunSize; i++) {
// create the object // create the object
Variant aNewVariant = new Variant(getName() + "_" + i); Variant aNewVariant = new Variant(getName() + "_" + i);
@@ -105,8 +110,8 @@ public class ROT2Test extends BaseTestCase {
} }
/** /**
* Another test would be to override this to always return the same name. * Another test would be to override this to always return the same
* That would really screw the ROT! * name. That would really screw the ROT!
* *
* @see java.lang.Object#toString() * @see java.lang.Object#toString()
*/ */

View File

@@ -3,8 +3,9 @@ package com.jacob.com;
import com.jacob.test.BaseTestCase; import com.jacob.test.BaseTestCase;
/** /**
* This tries to exercise ROT's garbage collection This is named this way because * This tries to exercise ROT's garbage collection This is named this way
* the build.xml ignores files ending in Test when building the binary zip file * because the build.xml ignores files ending in Test when building the binary
* zip file
* *
* This will eventually be changed to a unit test. * This will eventually be changed to a unit test.
* *
@@ -15,6 +16,9 @@ import com.jacob.test.BaseTestCase;
*/ */
public class ROT3Test extends BaseTestCase { public class ROT3Test extends BaseTestCase {
/**
* runs a multi-threaded test
*/
public void testROTVersion3() { public void testROTVersion3() {
ROT3TestThread threads[] = new ROT3TestThread[4]; ROT3TestThread threads[] = new ROT3TestThread[4];
for (int i = 0; i < threads.length; i++) { for (int i = 0; i < threads.length; i++) {
@@ -30,12 +34,14 @@ public class ROT3Test extends BaseTestCase {
*/ */
public class ROT3TestThread extends Thread { public class ROT3TestThread extends Thread {
private java.util.List variansCreatedInThisThread; private java.util.List<Variant> variansCreatedInThisThread;
private int initialRunSize = 0; private int initialRunSize = 0;
/** /**
* @param arg0 * @param arg0
* @param iStartCount
* the number of initial threads
*/ */
public ROT3TestThread(String arg0, int iStartCount) { public ROT3TestThread(String arg0, int iStartCount) {
super(arg0); super(arg0);
@@ -44,18 +50,20 @@ public class ROT3Test extends BaseTestCase {
} }
/** /**
* A semi-complexe serie of steps to put the ROT under stress. 1) * A semi-complex series of steps to put the ROT under stress. 1)
* discard half the objects we've created 2) if size is greater than 1 * discard half the objects we've created 2) if size is greater than 1
* but not a even number, add 1 new object 3) stop when size is 1. * but not a even number, add 1 new object 3) stop when size is 1.
* *
* @see java.lang.Runnable#run() * @see java.lang.Runnable#run()
*/ */
@SuppressWarnings("deprecation")
public void run() { public void run() {
// something that keeps object references around // something that keeps object references around
// so the gc can't collect them // so the gc can't collect them
// we need to create these in the thread so they end up in the right // we need to create these in the thread so they end up in the right
// ROT table // ROT table
variansCreatedInThisThread = new java.util.ArrayList(initialRunSize); variansCreatedInThisThread = new java.util.ArrayList<Variant>(
initialRunSize);
for (int i = 0; i < initialRunSize; i++) { for (int i = 0; i < initialRunSize; i++) {
// create the object // create the object
Variant aNewVariant = new Variant(getName() + "_" + i); Variant aNewVariant = new Variant(getName() + "_" + i);
@@ -92,8 +100,7 @@ public class ROT3Test extends BaseTestCase {
if (!ROT.USE_AUTOMATIC_GARBAGE_COLLECTION) { if (!ROT.USE_AUTOMATIC_GARBAGE_COLLECTION) {
// uses deprecated API to set up a special situation // uses deprecated API to set up a special situation
// because this is an ROT test // because this is an ROT test
ROT ROT.removeObject(variansCreatedInThisThread
.removeObject((JacobObject) variansCreatedInThisThread
.get(i - 1)); .get(i - 1));
} }
variansCreatedInThisThread.remove(i - 1); variansCreatedInThisThread.remove(i - 1);

View File

@@ -1,45 +1,52 @@
package com.jacob.com; package com.jacob.com;
import com.jacob.test.BaseTestCase; import com.jacob.test.BaseTestCase;
/** /**
* This tries to exercise ROT's garbage collection * This tries to exercise ROT's garbage collection
* *
* This will eventually be changed to a unit test. * This will eventually be changed to a unit test.
* <p> * <p>
* May need to run with some command line options (including from inside Eclipse). * May need to run with some command line options (including from inside
* Look in the docs area at the Jacob usage document for command line options. * Eclipse). Look in the docs area at the Jacob usage document for command line
* options.
*/ */
public class ROTTest extends BaseTestCase { public class ROTTest extends BaseTestCase {
/** /**
* verify the SystemProperty (classname).PutInROT functions as expected. * verify the SystemProperty (classname).PutInROT functions as expected. A
* A value of false means instances of the class are not put in the ROT * value of false means instances of the class are not put in the ROT Any o
* Any o ther value means they are * ther value means they are
*/ */
public void testDontFillROTSystemProperty() { public void testDontFillROTSystemProperty() {
debug("testDontFillROTSystemProperty: started"); debug("testDontFillROTSystemProperty: started");
// Make sure the class is loaded before running any of the tests // Make sure the class is loaded before running any of the tests
// class to load and any pre-defined Variants (FALSE and TRUE) to be created immediately // class to load and any pre-defined Variants (FALSE and TRUE) to be
// created immediately
VariantViaEvent.class.getName(); VariantViaEvent.class.getName();
if (ROT.getThreadObjects(true).entrySet().size() < 1) { if (ROT.getThreadObjects(true).entrySet().size() < 1) {
debug("Failure: ROT should have objects in it as soon as Variant class loaded."); debug("Failure: ROT should have objects in it as soon as Variant class loaded.");
} }
System.setProperty(VariantViaEvent.class.getName()+ROT.PUT_IN_ROT_SUFFIX,"false"); System.setProperty(VariantViaEvent.class.getName()
+ ROT.PUT_IN_ROT_SUFFIX, "false");
int countPriorToTest = ROT.getThreadObjects(true).entrySet().size(); int countPriorToTest = ROT.getThreadObjects(true).entrySet().size();
new VariantViaEvent(); new VariantViaEvent();
int countAfterAddWithoutROT = ROT.getThreadObjects(true).entrySet().size(); int countAfterAddWithoutROT = ROT.getThreadObjects(true).entrySet()
.size();
if (countAfterAddWithoutROT != countPriorToTest) { if (countAfterAddWithoutROT != countPriorToTest) {
debug("Failure: count prior: "+countPriorToTest+ debug("Failure: count prior: " + countPriorToTest
" and count after without ROT was: "+countAfterAddWithoutROT); + " and count after without ROT was: "
+ countAfterAddWithoutROT);
} }
System.setProperty(VariantViaEvent.class.getName()+ROT.PUT_IN_ROT_SUFFIX,"true"); System.setProperty(VariantViaEvent.class.getName()
+ ROT.PUT_IN_ROT_SUFFIX, "true");
new VariantViaEvent(); new VariantViaEvent();
int countAfterAddWithROT = ROT.getThreadObjects(true).entrySet().size(); int countAfterAddWithROT = ROT.getThreadObjects(true).entrySet().size();
if (countAfterAddWithROT != (countPriorToTest + 1)) { if (countAfterAddWithROT != (countPriorToTest + 1)) {
debug("Failure: count prior: "+countPriorToTest+ debug("Failure: count prior: " + countPriorToTest
" and count after with ROT was: "+countAfterAddWithROT); + " and count after with ROT was: " + countAfterAddWithROT);
} }
debug("testDontFillROTSystemProperty: completed"); debug("testDontFillROTSystemProperty: completed");
} }
@@ -56,7 +63,6 @@ public class ROTTest extends BaseTestCase {
int loopSize = 10000; int loopSize = 10000;
int sizeExpectedAfterBuild = 0; int sizeExpectedAfterBuild = 0;
debug("testGCBehavior: started"); debug("testGCBehavior: started");
debug("creating 10,000 object sets"); debug("creating 10,000 object sets");
// cause classes to get loaded and any static instances to be created // cause classes to get loaded and any static instances to be created
@@ -73,7 +79,8 @@ public class ROTTest extends BaseTestCase {
if (sizeAfterBuild < sizeExpectedAfterBuild) { if (sizeAfterBuild < sizeExpectedAfterBuild) {
debug("Something got GC'd: " + sizeAfterBuild); debug("Something got GC'd: " + sizeAfterBuild);
} else if (sizeAfterBuild > sizeExpectedAfterBuild) { } else if (sizeAfterBuild > sizeExpectedAfterBuild) {
debug("More: "+sizeAfterBuild+" than expected: "+sizeExpectedAfterBuild); debug("More: " + sizeAfterBuild + " than expected: "
+ sizeExpectedAfterBuild);
} else { } else {
debug("They're all there"); debug("They're all there");
} }
@@ -82,19 +89,24 @@ public class ROTTest extends BaseTestCase {
for (int i = 0; i <= loopSize * 2; i++) { for (int i = 0; i <= loopSize * 2; i++) {
new String("this is just some text to see if we can force gc " + i); new String("this is just some text to see if we can force gc " + i);
} }
// storage will hold weak references until the next JacobObject is created // storage will hold weak references until the next JacobObject is
// created
System.gc(); System.gc();
sizeBeforeGC = ROT.getThreadObjects(false).size(); sizeBeforeGC = ROT.getThreadObjects(false).size();
debug("Objects left after flood and gc but before adding a new object that clean's up weak references: "+sizeBeforeGC); debug("Objects left after flood and gc but before adding a new object that clean's up weak references: "
+ sizeBeforeGC);
debug("Creating single object. This adds one and causes ROT to clean up GC'd"); debug("Creating single object. This adds one and causes ROT to clean up GC'd");
new JacobObject(); new JacobObject();
sizeAfterGC = ROT.getThreadObjects(false).size(); sizeAfterGC = ROT.getThreadObjects(false).size();
debug("Objects left after adding one (caused weak ref objects to be removed): "+sizeAfterGC); debug("Objects left after adding one (caused weak ref objects to be removed): "
+ sizeAfterGC);
new JacobObject(); new JacobObject();
if (ROT.getThreadObjects(false).size() != sizeAfterGC + 1) { if (ROT.getThreadObjects(false).size() != sizeAfterGC + 1) {
debug("Unexpected number of objects after adding only one more "+ROT.getThreadObjects(false).size()); debug("Unexpected number of objects after adding only one more "
+ ROT.getThreadObjects(false).size());
} else { } else {
debug("Found number expected after adding one more " +(sizeAfterGC+1) ); debug("Found number expected after adding one more "
+ (sizeAfterGC + 1));
} }
ROT.clearObjects(); ROT.clearObjects();
if (ROT.getThreadObjects(false) == null) { if (ROT.getThreadObjects(false) == null) {

View File

@@ -7,11 +7,15 @@ import com.jacob.test.BaseTestCase;
/** /**
* test cases that should exercise the new date conversion code * test cases that should exercise the new date conversion code
* <p> * <p>
* May need to run with some command line options (including from inside Eclipse). * May need to run with some command line options (including from inside
* Look in the docs area at the Jacob usage document for command line options. * Eclipse). Look in the docs area at the Jacob usage document for command line
* options.
*/ */
public class VariantDateTest extends BaseTestCase { public class VariantDateTest extends BaseTestCase {
/**
* verify the conversion of Variants into java dates
*/
public void testVariantDate() { public void testVariantDate() {
Date now = new Date(); Date now = new Date();
Variant holder = new Variant(); Variant holder = new Variant();
@@ -25,6 +29,10 @@ public class VariantDateTest extends BaseTestCase {
} }
/**
* verify that the Variant constructor accepts Java dates and converts them
* correctly
*/
public void testVariantDateToJavaObject() { public void testVariantDateToJavaObject() {
Date now = new Date(); Date now = new Date();
Variant holder = new Variant(now); Variant holder = new Variant(now);
@@ -33,16 +41,19 @@ public class VariantDateTest extends BaseTestCase {
Date retrievedNow = holder.getJavaDate(); Date retrievedNow = holder.getJavaDate();
retrievedNow = dateVariant.getJavaDate(); retrievedNow = dateVariant.getJavaDate();
if (!now.equals(retrievedNow)) { if (!now.equals(retrievedNow)) {
fail("Variant Date Test (1) failed " +now+ " != " +retrievedNow ); fail("Variant Date Test (1) failed " + now + " != "
+ retrievedNow);
} else { } else {
// System.out.println("Variant Date Test (1) passed"); // System.out.println("Variant Date Test (1) passed");
} }
// verify auto typecasting works // verify auto typecasting works
retrievedNow = (Date) dateVariant.toJavaObject(); retrievedNow = (Date) dateVariant.toJavaObject();
if (!now.equals(retrievedNow)) { if (!now.equals(retrievedNow)) {
fail("Variant Date Test (2) failed " +now+ " != " +retrievedNow ); fail("Variant Date Test (2) failed " + now + " != "
+ retrievedNow);
} else { } else {
//System.out.println("Variant Date Test (2) passed "+retrievedNow); // System.out.println("Variant Date Test (2) passed
// "+retrievedNow);
} }
Variant intVariant = new Variant(4); Variant intVariant = new Variant(4);

View File

@@ -1,6 +1,7 @@
package com.jacob.com; package com.jacob.com;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date; import java.util.Date;
import com.jacob.test.BaseTestCase; import com.jacob.test.BaseTestCase;
@@ -9,17 +10,18 @@ import com.jacob.test.BaseTestCase;
* runs through some of the get and set methods on Variant * runs through some of the get and set methods on Variant
* *
* <p> * <p>
* May need to run with some command line options (including from inside Eclipse). * May need to run with some command line options (including from inside
* Look in the docs area at the Jacob usage document for command line options. * Eclipse). Look in the docs area at the Jacob usage document for command line
* options.
*/ */
public class VariantTest extends BaseTestCase { public class VariantTest extends BaseTestCase {
/** /**
* This verifies that toJavaObject() works for all of the * This verifies that toJavaObject() works for all of the main data types
* main data types when they exist as a byRef version. * when they exist as a byRef version.
* <p> * <p>
* It compares the toJavaObject() for a byref against the * It compares the toJavaObject() for a byref against the toJavaObject() for
* toJavaObject() for the regular. * the regular.
* *
*/ */
public void testByRefToJavaObject() { public void testByRefToJavaObject() {
@@ -29,48 +31,42 @@ public class VariantTest extends BaseTestCase {
v = new Variant(new Float(53.3), false); v = new Variant(new Float(53.3), false);
vByRef = new Variant(new Float(53.3), true); vByRef = new Variant(new Float(53.3), true);
if (!v.toJavaObject().equals(vByRef.toJavaObject())) { if (!v.toJavaObject().equals(vByRef.toJavaObject())) {
fail(v.toString() + " could not make type " fail(v.toString() + " could not make type " + v.getvt() + " and "
+ v.getvt() +" and "+ vByRef.getvt() + vByRef.getvt() + " java objects come out the same");
+" java objects come out the same");
} }
v = new Variant(new Double(53.3), false); v = new Variant(new Double(53.3), false);
vByRef = new Variant(new Double(53.3), true); vByRef = new Variant(new Double(53.3), true);
if (!v.toJavaObject().equals(vByRef.toJavaObject())) { if (!v.toJavaObject().equals(vByRef.toJavaObject())) {
fail(v.toString() + " could not make type " fail(v.toString() + " could not make type " + v.getvt() + " and "
+ v.getvt() +" and "+ vByRef.getvt() + vByRef.getvt() + " java objects come out the same");
+" java objects come out the same");
} }
v = new Variant(new Boolean(true), false); v = new Variant(new Boolean(true), false);
vByRef = new Variant(new Boolean(true), true); vByRef = new Variant(new Boolean(true), true);
if (!v.toJavaObject().equals(vByRef.toJavaObject())) { if (!v.toJavaObject().equals(vByRef.toJavaObject())) {
fail(v.toString() + " could not make type " fail(v.toString() + " could not make type " + v.getvt() + " and "
+ v.getvt() +" and "+ vByRef.getvt() + vByRef.getvt() + " java objects come out the same");
+" java objects come out the same");
} }
v = new Variant(new Integer(53), false); v = new Variant(new Integer(53), false);
vByRef = new Variant(new Integer(53), true); vByRef = new Variant(new Integer(53), true);
if (!v.toJavaObject().equals(vByRef.toJavaObject())) { if (!v.toJavaObject().equals(vByRef.toJavaObject())) {
fail(v.toString() + " could not make type " fail(v.toString() + " could not make type " + v.getvt() + " and "
+ v.getvt() +" and "+ vByRef.getvt() + vByRef.getvt() + " java objects come out the same");
+" java objects come out the same");
} }
v = new Variant(new Short((short) 53), false); v = new Variant(new Short((short) 53), false);
vByRef = new Variant(new Short((short) 53), true); vByRef = new Variant(new Short((short) 53), true);
if (!v.toJavaObject().equals(vByRef.toJavaObject())) { if (!v.toJavaObject().equals(vByRef.toJavaObject())) {
fail(v.toString() + " could not make type " fail(v.toString() + " could not make type " + v.getvt() + " and "
+ v.getvt() +" and "+ vByRef.getvt() + vByRef.getvt() + " java objects come out the same");
+" java objects come out the same");
} }
v = new Variant("53.33", false); v = new Variant("53.33", false);
vByRef = new Variant("53.33", true); vByRef = new Variant("53.33", true);
if (!v.toJavaObject().equals(vByRef.toJavaObject())) { if (!v.toJavaObject().equals(vByRef.toJavaObject())) {
fail(v.toString() + " could not make type " fail(v.toString() + " could not make type " + v.getvt() + " and "
+ v.getvt() +" and "+ vByRef.getvt() + vByRef.getvt() + " java objects come out the same");
+" java objects come out the same");
} }
// Ugh, you have to pick a magic number whose scale is less than 28 // Ugh, you have to pick a magic number whose scale is less than 28
@@ -79,21 +75,71 @@ public class VariantTest extends BaseTestCase {
v = new Variant(testDecimal, false); v = new Variant(testDecimal, false);
vByRef = new Variant(testDecimal, true); vByRef = new Variant(testDecimal, true);
if (!v.toJavaObject().equals(vByRef.toJavaObject())) { if (!v.toJavaObject().equals(vByRef.toJavaObject())) {
fail(v.toString() + " could not make type " fail(v.toString() + " could not make type " + v.getvt() + " and "
+ v.getvt() +" and "+ vByRef.getvt() + vByRef.getvt() + " java objects come out the same");
+" java objects come out the same");
} }
Date now = new Date(); Date now = new Date();
v = new Variant(now, false); v = new Variant(now, false);
vByRef = new Variant(now, true); vByRef = new Variant(now, true);
if (!v.toJavaObject().equals(vByRef.toJavaObject())) { if (!v.toJavaObject().equals(vByRef.toJavaObject())) {
fail(v.toString() + " could not make type " fail(v.toString() + " could not make type " + v.getvt() + " and "
+ v.getvt() +" and "+ vByRef.getvt() + vByRef.getvt() + " java objects come out the same");
+" java objects come out the same"); }
} }
/**
* try and test VT_I8. This should only work on 64 bit machines
*/
public void testLong() {
Variant v = null;
Variant vByRef = null;
long longNumber = 1L << 40;
v = new Variant(new Long(longNumber), false);
vByRef = new Variant(new Long(longNumber), true);
assertEquals("Could recover long number " + longNumber, v.getLong(),
longNumber);
assertEquals("Could not make long number " + longNumber
+ " come out the same for get and getByRef()",
v.toJavaObject(), vByRef.toJavaObject());
v = new Variant("" + longNumber);
v.changeType(Variant.VariantLongInt);
assertEquals("Conversion from string to long didn't work ",
v.getLong(), longNumber);
}
/**
* do some testing around currencies
*/
public void testCurrencyHandling() {
Variant v = null;
Variant vByRef = null;
// need to do currency also // need to do currency also
// currency is an integer scaled up by 10,000 to give 4 digits to the
// right of the decimal
int currencyScale = 10000;
long twentyThousand = 20000 * currencyScale;
Currency twentyThousandAsCurrency = new Currency(twentyThousand);
v = new Variant(twentyThousandAsCurrency, false);
vByRef = new Variant(twentyThousandAsCurrency, true);
if (!(v.toJavaObject() instanceof Currency)) {
fail("v.toJavaObject was not Long for currency but was: "
+ v.toJavaObject());
}
if (!v.toJavaObject().equals(vByRef.toJavaObject())) {
fail(v.toString() + " could not make type " + v.getvt() + " and "
+ vByRef.getvt() + " java objects come out the same");
}
long twentyThousandDotSeven = twentyThousand + 700;
Currency twentyThousandDotSevenAsCurrency = new Currency(
twentyThousandDotSeven);
// use the primitive constructor
v = new Variant(twentyThousandDotSevenAsCurrency);
assertEquals("failed test with " + twentyThousandDotSeven,
twentyThousandDotSeven, v.getCurrency().longValue());
} }
/** /**
@@ -114,7 +160,8 @@ public class VariantTest extends BaseTestCase {
*/ */
public void testSomeChangeVT() { public void testSomeChangeVT() {
Variant v; Variant v;
// the code shows e shouldn't need to use a returned Variant but the test says we do // the code shows e shouldn't need to use a returned Variant but the
// test says we do
Variant vConverted; Variant vConverted;
v = new Variant(53.3); v = new Variant(53.3);
short originalVT = v.getvt(); short originalVT = v.getvt();
@@ -123,19 +170,15 @@ public class VariantTest extends BaseTestCase {
modifier = Variant.VariantShort; modifier = Variant.VariantShort;
vConverted = v.changeType(modifier); vConverted = v.changeType(modifier);
if (vConverted.getvt() != modifier) { if (vConverted.getvt() != modifier) {
fail("Failed to change Variant "+originalVT fail("Failed to change Variant " + originalVT + " using mask "
+ " using mask "+modifier + modifier + " resulted in " + vConverted.getvt());
+ " resulted in "+vConverted.getvt()
);
} }
modifier = Variant.VariantString; modifier = Variant.VariantString;
vConverted = v.changeType(modifier); vConverted = v.changeType(modifier);
if (vConverted.getvt() != modifier) { if (vConverted.getvt() != modifier) {
fail("Failed to change Variant "+originalVT fail("Failed to change Variant " + originalVT + " using mask "
+ " using mask "+modifier + modifier + " resulted in " + vConverted.getvt());
+ " resulted in "+vConverted.getvt()
);
} }
// can't convert to byref! // can't convert to byref!
@@ -143,9 +186,8 @@ public class VariantTest extends BaseTestCase {
vConverted = v.changeType(modifier); vConverted = v.changeType(modifier);
if (vConverted.getvt() == modifier) { if (vConverted.getvt() == modifier) {
fail("Should not have been able to change Variant " + originalVT fail("Should not have been able to change Variant " + originalVT
+ " using mask "+modifier + " using mask " + modifier + " resulted in "
+ " resulted in "+vConverted.getvt() + vConverted.getvt());
);
} }
} }
@@ -160,23 +202,27 @@ public class VariantTest extends BaseTestCase {
try { try {
if (v.getvt() == Variant.VariantEmpty) { if (v.getvt() == Variant.VariantEmpty) {
// successful // successful
// System.out.println("Variant initialized without parameters correctly set to empty"); // System.out.println("Variant initialized without parameters
// correctly set to empty");
} else { } else {
throw new RuntimeException("getvt() on uninitialized variant shoud have returned VariantEmpty, instead returned "+v.getvt()); throw new RuntimeException(
"getvt() on uninitialized variant shoud have returned VariantEmpty, instead returned "
+ v.getvt());
} }
} catch (IllegalStateException ise) { } catch (IllegalStateException ise) {
throw new RuntimeException("getvt() on uninitialized variant shoud have succeeded, but instead threw exception"); throw new RuntimeException(
"getvt() on uninitialized variant shoud have succeeded, but instead threw exception");
} }
try { try {
v.toString(); v.toString();
} catch (IllegalStateException ise) { } catch (IllegalStateException ise) {
fail("toString() should never throw a runtime exception"); fail("toString() should never throw a runtime exception");
throw new RuntimeException("toString() should not blow up even with uninitialized Variant"); throw new RuntimeException(
"toString() should not blow up even with uninitialized Variant");
} }
} }
/** /**
* *
* verify the toString() method does not do type conversion * verify the toString() method does not do type conversion
@@ -186,7 +232,8 @@ public class VariantTest extends BaseTestCase {
v = new Variant(true); v = new Variant(true);
v.toString(); v.toString();
if (v.getvt() != Variant.VariantBoolean) { if (v.getvt() != Variant.VariantBoolean) {
throw new RuntimeException("toString() converted boolean to something else"); throw new RuntimeException(
"toString() converted boolean to something else");
} else { } else {
// fail("toString() correctly does not convert type"); // fail("toString() correctly does not convert type");
} }
@@ -196,7 +243,8 @@ public class VariantTest extends BaseTestCase {
v = new Variant(false); v = new Variant(false);
v.toString(); v.toString();
if (v.getvt() != Variant.VariantBoolean) { if (v.getvt() != Variant.VariantBoolean) {
throw new RuntimeException("toString() converted boolean to something else"); throw new RuntimeException(
"toString() converted boolean to something else");
} else { } else {
// fail("toString() correctly does not convert type"); // fail("toString() correctly does not convert type");
} }
@@ -205,6 +253,10 @@ public class VariantTest extends BaseTestCase {
} }
} }
/**
* Verify that booleans can be released. Part of the suite that checks all
* types.
*/
public void testSafeReleaseBoolean() { public void testSafeReleaseBoolean() {
Variant v; Variant v;
v = new Variant(true); v = new Variant(true);
@@ -216,7 +268,8 @@ public class VariantTest extends BaseTestCase {
fail("IllegalStateException should have been thrown when querying safeReleased object"); fail("IllegalStateException should have been thrown when querying safeReleased object");
throw new RuntimeException("test failed"); throw new RuntimeException("test failed");
} catch (IllegalStateException ise) { } catch (IllegalStateException ise) {
//System.out.println("IllegalStateException correctly thrown after safeRelease"); // System.out.println("IllegalStateException correctly thrown after
// safeRelease");
} }
v = new Variant(true); v = new Variant(true);
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
@@ -230,7 +283,8 @@ public class VariantTest extends BaseTestCase {
fail("IllegalStateException should have been thrown when querying ComThread.Release"); fail("IllegalStateException should have been thrown when querying ComThread.Release");
throw new RuntimeException("test failed"); throw new RuntimeException("test failed");
} catch (IllegalStateException ise) { } catch (IllegalStateException ise) {
//System.out.println("IllegalStateException correctly thrown after ComThread.Release"); // System.out.println("IllegalStateException correctly thrown after
// ComThread.Release");
} }
} }
@@ -239,7 +293,8 @@ public class VariantTest extends BaseTestCase {
* *
*/ */
public void testSafeReleaseConstant() { public void testSafeReleaseConstant() {
//System.out.println("Using Static constant Variant - should never throw access violation"); // System.out.println("Using Static constant Variant - should never
// throw access violation");
Variant.VT_TRUE.safeRelease(); Variant.VT_TRUE.safeRelease();
if (Variant.VT_TRUE.getBoolean() != true) { if (Variant.VT_TRUE.getBoolean() != true) {
fail("VT_TRUE has been broken by SafeRelease()"); fail("VT_TRUE has been broken by SafeRelease()");
@@ -265,9 +320,9 @@ public class VariantTest extends BaseTestCase {
} }
/** /**
* this used to try and and create an access violation but that * this used to try and and create an access violation but that didn't work
* didn't work and now the methods on the Variant are smarter about * and now the methods on the Variant are smarter about working after a
* working after a release * release
* *
*/ */
public void testSafeReleaseString() { public void testSafeReleaseString() {
@@ -281,7 +336,8 @@ public class VariantTest extends BaseTestCase {
fail("IllegalStateException should have been thrown when querying safeReleased object"); fail("IllegalStateException should have been thrown when querying safeReleased object");
throw new RuntimeException("test failed"); throw new RuntimeException("test failed");
} catch (IllegalStateException ise) { } catch (IllegalStateException ise) {
//System.out.println("IllegalStateException correctly thrown after safeRelease"); // System.out.println("IllegalStateException correctly thrown after
// safeRelease");
} }
} }
@@ -310,7 +366,6 @@ public class VariantTest extends BaseTestCase {
fail("confused a boolean with VT_FALSE"); fail("confused a boolean with VT_FALSE");
} }
} }
/** /**
@@ -320,8 +375,8 @@ public class VariantTest extends BaseTestCase {
public void testPutsAndGets() { public void testPutsAndGets() {
Variant v = new Variant(); Variant v = new Variant();
v.putInt((int)10); v.putInt(10);
assertEquals("int test failed", (int)10, v.getInt()); assertEquals("int test failed", 10, v.getInt());
v.putShort((short) 20); v.putShort((short) 20);
assertEquals("short test failed", (short) 20, v.getShort()); assertEquals("short test failed", (short) 20, v.getShort());
@@ -348,14 +403,15 @@ public class VariantTest extends BaseTestCase {
v.putBoolean(false); v.putBoolean(false);
assertEquals("failed boolean test(false)", false, v.getBoolean()); assertEquals("failed boolean test(false)", false, v.getBoolean());
v.putCurrency(123456789123456789L); long originalValue = 123456789123456789L;
assertEquals("failed currency test",123456789123456789L, v.getCurrency()); v.putCurrency(new Currency(originalValue));
assertEquals("failed currency test", 123456789123456789L, v
.getCurrency().longValue());
BigDecimal testDecimal = new BigDecimal("22.222"); BigDecimal testDecimal = new BigDecimal("22.222");
v.putDecimal(testDecimal); v.putDecimal(testDecimal);
assertEquals("failed BigDecimal test", testDecimal, v.getDecimal()); assertEquals("failed BigDecimal test", testDecimal, v.getDecimal());
Date ourDate = new Date(); Date ourDate = new Date();
v.putDate(ourDate); v.putDate(ourDate);
Date retrievedDate = v.getJavaDate(); Date retrievedDate = v.getJavaDate();
@@ -397,8 +453,133 @@ public class VariantTest extends BaseTestCase {
} }
/** /**
* Spin up a lot of threads and have them all create variants * verify decimal works right
* 3/2007 there have been several reports in multi-threaded servers that show init() failing */
public void testDecimalConversion() {
Variant v = new Variant();
v.changeType(Variant.VariantDecimal);
for (int i = 10; i >= -10; i--) {
v.putDecimal(new BigDecimal(i));
// first see if we can get it back as decimal
assertEquals("conversion back to decimal failed " + i,
new BigDecimal(i), v.getDecimal());
v.changeType(Variant.VariantFloat);
// now see if a float conversion would work
assertEquals("conversion to float failed " + i, new Float(i), v
.getFloat());
// now convert it back to decimal for reassignment
v.changeType(Variant.VariantDecimal);
assertTrue("Failed conversion of type back to Decimal " + i, v
.getvt() == Variant.VariantDecimal);
}
}
/**
* for(BigDecimal i in 79228162514264337593543950330.0 ..
* 79228162514264337593543950341.0) { com.jacob.com.Variant dv = new
* com.jacob.com.Variant(i, false) println i + " : " + dv.getDecimal() }
*
*/
public void testLargeDecimals() {
// the largest decimal number, not in hex is
// 7922816251426433759354395033.0
BigInteger theStartDigits = new BigInteger("ffffffffffffffffffffff00",
16);
BigInteger theMaxDigits = new BigInteger("ffffffffffffffffffffffff", 16);
BigDecimal startDecimal = new BigDecimal(theStartDigits);
BigDecimal endDecimal = new BigDecimal(theMaxDigits);
BigDecimal incrementDecimal = new BigDecimal(1);
BigDecimal testDecimal = startDecimal;
Variant testVariant;
while (endDecimal.compareTo(testDecimal) >= 0) {
testVariant = new Variant(testDecimal, false);
BigDecimal result = testVariant.getDecimal();
assertEquals(testDecimal, result);
testDecimal = testDecimal.add(incrementDecimal);
}
// test Decimal is now too large
try {
new Variant(testDecimal, false);
} catch (IllegalArgumentException iae) {
// System.out.println("Caught expected exception");
}
// lets try something different. we can call putVariant with rounding
// enabled
testVariant = new Variant();
testVariant.changeType(Variant.VariantDecimal);
try {
testVariant.putDecimal(endDecimal.setScale(30));
fail("Should have thrown exception with scale of 30 and no rounding");
} catch (IllegalArgumentException iae) {
// should have caught this exception
}
// now we test with a negative scale. Note that you can't do with
// without some magic, in this case scientific notation
try {
testVariant.putDecimal(new BigDecimal("700E24"));
assertTrue(new BigDecimal("700E24").compareTo(testVariant
.getDecimal()) == 0);
} catch (IllegalArgumentException iae) {
// should have caught this exception
}
testVariant.putDecimal(VariantUtilities
.roundToMSDecimal(new BigDecimal("700E24")));
// use compareTo because it takes into account varying scales
assertTrue(new BigDecimal("700E24").compareTo(testVariant.getDecimal()) == 0);
// This passes because the number is within range.
testVariant.putDecimal(endDecimal);
// this should pass because we have rounding turned on
// it turns out the max number gets more digits when
// it's scale is set to 30. so we can't use the max number when there is
// a scale
BigDecimal modifiedDecimal = endDecimal;
System.out.println("integer piece starts as "
+ modifiedDecimal.unscaledValue().toString(16) + " scale=: "
+ modifiedDecimal.scale());
System.out.println("integer piece after rounding without scale is "
+ VariantUtilities.roundToMSDecimal(modifiedDecimal)
.unscaledValue().toString(16) + " scale=: "
+ modifiedDecimal.scale());
System.out.println("integer piece after rounding with scale 30 is "
+ VariantUtilities.roundToMSDecimal(
modifiedDecimal.setScale(30)).unscaledValue().toString(
16) + " scale=: " + modifiedDecimal.scale());
try {
testVariant.putDecimal(VariantUtilities
.roundToMSDecimal(modifiedDecimal.setScale(30)));
fail("should have thrown an exception for a number whose scale "
+ "change created too many digits to be represented.");
} catch (IllegalArgumentException iae) {
// should catch an exception here because the rounding after scale
// change would have made the number too large
}
System.out.println("");
modifiedDecimal = endDecimal.subtract(incrementDecimal);
System.out.println("integer piece starts as "
+ modifiedDecimal.unscaledValue().toString(16) + " scale=: "
+ modifiedDecimal.scale());
System.out.println("integer piece after rounding without scale is "
+ VariantUtilities.roundToMSDecimal(modifiedDecimal)
.unscaledValue().toString(16) + " scale=: "
+ modifiedDecimal.scale());
System.out.println("integer piece after rounding with scale 30 is "
+ VariantUtilities.roundToMSDecimal(
modifiedDecimal.setScale(30)).unscaledValue().toString(
16) + " scale=: " + modifiedDecimal.scale());
testVariant.putDecimal(VariantUtilities
.roundToMSDecimal(modifiedDecimal.setScale(30)));
System.out.println("");
}
/**
* Spin up a lot of threads and have them all create variants 3/2007 there
* have been several reports in multi-threaded servers that show init()
* failing
* *
*/ */
public void testManyThreadedInit() { public void testManyThreadedInit() {
@@ -407,12 +588,10 @@ public class VariantTest extends BaseTestCase {
System.out.println("Starting thread test (" + threads.length System.out.println("Starting thread test (" + threads.length
+ " threads each creating 10000 objects)." + " threads each creating 10000 objects)."
+ " This may take 30 seconds or more."); + " This may take 30 seconds or more.");
for (int i = 0; i < threads.length; i++) for (int i = 0; i < threads.length; i++) {
{
threads[i] = new VariantInitTestThread("thread-" + i, 10000); threads[i] = new VariantInitTestThread("thread-" + i, 10000);
} }
for (int i = 0; i < threads.length; i++) for (int i = 0; i < threads.length; i++) {
{
threads[i].start(); threads[i].start();
} }
int numComplete = 0; int numComplete = 0;
@@ -435,35 +614,41 @@ public class VariantTest extends BaseTestCase {
} }
/** /**
* a class to create variants in seperate threads * a class to create variants in separate threads
* @author joe
* *
*/ */
class VariantInitTestThread extends Thread class VariantInitTestThread extends Thread {
{
private boolean isComplete = false; private boolean isComplete = false;
private int initialRunSize = 0; private int initialRunSize = 0;
/** /**
* @param arg0 * @param newThreadName
* the name for the thread
* @param iStartCount
* number of threads to start with
*/ */
public VariantInitTestThread(String newThreadName, int iStartCount) public VariantInitTestThread(String newThreadName, int iStartCount) {
{
super(newThreadName); super(newThreadName);
initialRunSize = iStartCount; initialRunSize = iStartCount;
} }
/**
* getter so master can see if thread is done
*
* @return state of complete flag
*/
public boolean isComplete() { public boolean isComplete() {
return isComplete; return isComplete;
} }
/** /**
* Blow out a bunch of Variants * Blow out a bunch of Variants
* *
* @see java.lang.Runnable#run() * @see java.lang.Runnable#run()
*/ */
public void run() public void run() {
{
for (int variantIndex = 0; variantIndex < initialRunSize; variantIndex++) { for (int variantIndex = 0; variantIndex < initialRunSize; variantIndex++) {
try { try {
Thread.yield(); Thread.yield();

View File

@@ -0,0 +1,33 @@
package com.jacob.com;
import java.util.Date;
import com.jacob.test.BaseTestCase;
/**
* This class should test some of the converter capabilities
*
*/
public class VariantUtilitiesTest extends BaseTestCase {
/**
* verify that dispatch can convert from object to variant and that the
* variant holds the right value
*/
public void testConverters() {
Date testDate = new Date();
Variant fromDate = VariantUtilities.objectToVariant(testDate);
Date returnedDate = fromDate.getJavaDate();
// System.out.println("test date is "+testDate);
// System.out.println("VariantDate is "+fromDate.getJavaDate());
assertTrue("Could not call obj2variant(Date) and get it to work",
testDate.equals(returnedDate));
Currency someMoney = new Currency(12349876L);
Variant fromMoney = VariantUtilities.objectToVariant(someMoney);
Currency someMoneyConverted = fromMoney.getCurrency();
assertTrue("Could not call obj2variant(Long) and get it to work",
someMoney.equals(someMoneyConverted));
System.out.println("currency returned was: " + someMoneyConverted);
}
}

View File

@@ -7,6 +7,9 @@ import junit.framework.TestCase;
import com.jacob.com.JacobObject; import com.jacob.com.JacobObject;
/** /**
* This base test class may require that the unittest package be
* 'jacob-project/unittest' be on the classpath to find some resources.
*
* May need to run with some command line options (including from inside * May need to run with some command line options (including from inside
* Eclipse). Look in the docs area at the Jacob usage document for command line * Eclipse). Look in the docs area at the Jacob usage document for command line
* options. Or try these: * options. Or try these:
@@ -39,6 +42,7 @@ public class BaseTestCase extends TestCase {
JacobObject foo = new JacobObject(); JacobObject foo = new JacobObject();
assertNotNull(foo); assertNotNull(foo);
} }
/** /**
* *
* @return a simple VB script that generates the result "3" * @return a simple VB script that generates the result "3"
@@ -49,15 +53,17 @@ public class BaseTestCase extends TestCase {
} }
/** /**
* Converts the class name into a path and appends the resource name. * Converts the class name into a path and appends the resource name. Used
* Used to derive the path to a resouce in the file system * to derive the path to a resource in the file system where the resource is
* where the resource is co-located with the referenced class. * co-located with the referenced class.
* *
* @param resourceName * @param resourceName
* @param classInSamePackageAsResource * @param classInSamePackageAsResource
* @return a class loader compatible fully qualified file system path to a resource * @return a class loader compatible fully qualified file system path to a
* resource
*/ */
public String getJavaFilePathToPackageResource(String resourceName, @SuppressWarnings("unchecked")
private String getJavaFilePathToPackageResource(String resourceName,
Class classInSamePackageAsResource) { Class classInSamePackageAsResource) {
String classPackageName = classInSamePackageAsResource.getName(); String classPackageName = classInSamePackageAsResource.getName();
@@ -68,7 +74,8 @@ public class BaseTestCase extends TestCase {
classPackageName = classPackageName.substring(0, i); classPackageName = classPackageName.substring(0, i);
} }
// change all "." to ^ for later conversion to "/" so we can append resource names with "." // change all "." to ^ for later conversion to "/" so we can append
// resource names with "."
classPackageName = classPackageName.replace('.', '^'); classPackageName = classPackageName.replace('.', '^');
System.out.println("classPackageName: " + classPackageName); System.out.println("classPackageName: " + classPackageName);
String fullPathToResource; String fullPathToResource;
@@ -81,30 +88,35 @@ public class BaseTestCase extends TestCase {
fullPathToResource = fullPathToResource.replace('^', '/'); fullPathToResource = fullPathToResource.replace('^', '/');
System.out.println("fullPathToResource: " + fullPathToResource); System.out.println("fullPathToResource: " + fullPathToResource);
URL urlToLibrary = URL urlToLibrary = classInSamePackageAsResource.getClassLoader()
classInSamePackageAsResource.getClassLoader().getResource(fullPathToResource); .getResource(fullPathToResource);
assertNotNull("URL to resource "+resourceName+" should not be null",urlToLibrary); assertNotNull("URL to resource " + resourceName
+ " should not be null."
+ " You probably need to add 'unittest' to the"
+ " classpath so the tests can find resources", urlToLibrary);
String fullPathToResourceAsFile = urlToLibrary.getFile(); String fullPathToResourceAsFile = urlToLibrary.getFile();
System.out.println("url to library: " + urlToLibrary); System.out.println("url to library: " + urlToLibrary);
System.out.println("fullPathToResourceAsFile: "+fullPathToResourceAsFile); System.out.println("fullPathToResourceAsFile: "
+ fullPathToResourceAsFile);
return fullPathToResourceAsFile; return fullPathToResourceAsFile;
} }
/** /**
* Converts the class name into a path and appends the resource name. * Converts the class name into a path and appends the resource name. Used
* Used to derive the path to a resouce in the file system * to derive the path to a resource in the file system where the resource is
* where the resource is co-located with the referenced class. * co-located with the referenced class.
* *
* @param resourceName * @param resourceName
* @param classInSamePackageAsResource * @param classInSamePackageAsResource
* @return returns the path in the file system of the requested resource in windows c * @return returns the path in the file system of the requested resource in
* compatible format * windows c compatible format
*/ */
public String getWindowsFilePathToPackageResource( @SuppressWarnings("unchecked")
String resourceName, Class classInSamePackageAsResource) { public String getWindowsFilePathToPackageResource(String resourceName,
String javaFilePath = getJavaFilePathToPackageResource( Class classInSamePackageAsResource) {
resourceName, classInSamePackageAsResource); String javaFilePath = getJavaFilePathToPackageResource(resourceName,
classInSamePackageAsResource);
javaFilePath = javaFilePath.replace('/', '\\'); javaFilePath = javaFilePath.replace('/', '\\');
return javaFilePath.substring(1); return javaFilePath.substring(1);
} }
@@ -115,10 +127,11 @@ public class BaseTestCase extends TestCase {
* @param classInSamePackageAsResource * @param classInSamePackageAsResource
* @return a resource located in the same package as the passed in class * @return a resource located in the same package as the passed in class
*/ */
public Object getPackageResource(String resourceName, @SuppressWarnings( { "unused", "unchecked" })
private Object getPackageResource(String resourceName,
Class classInSamePackageAsResource) { Class classInSamePackageAsResource) {
String fullPathToResource = getJavaFilePathToPackageResource(resourceName, String fullPathToResource = getJavaFilePathToPackageResource(
classInSamePackageAsResource); resourceName, classInSamePackageAsResource);
ClassLoader localClassLoader = classInSamePackageAsResource ClassLoader localClassLoader = classInSamePackageAsResource
.getClassLoader(); .getClassLoader();
if (null == localClassLoader) { if (null == localClassLoader) {
@@ -132,13 +145,13 @@ public class BaseTestCase extends TestCase {
* load a library from same place in the file system that the class was * load a library from same place in the file system that the class was
* loaded from. * loaded from.
* <p> * <p>
* This is an attempt to let unit tests run without having to run * This is an attempt to let unit tests run without having to run regsvr32.
* regsvr32.
* *
* @param libraryName * @param libraryName
* @param classInSamePackageAsResource * @param classInSamePackageAsResource
*/ */
public void loadLibraryFromClassPackage(String libraryName, @SuppressWarnings( { "unchecked", "unused" })
private void loadLibraryFromClassPackage(String libraryName,
Class classInSamePackageAsResource) { Class classInSamePackageAsResource) {
String libraryNameWithSuffix = ""; String libraryNameWithSuffix = "";
String fullLibraryNameWithPath = ""; String fullLibraryNameWithPath = "";
@@ -149,7 +162,8 @@ public class BaseTestCase extends TestCase {
} else { } else {
fail("can't create full library name " + libraryName); fail("can't create full library name " + libraryName);
} }
// generate the path the classloader would use to find this on the classpath // generate the path the classloader would use to find this on the
// classpath
fullLibraryNameWithPath = getJavaFilePathToPackageResource( fullLibraryNameWithPath = getJavaFilePathToPackageResource(
libraryNameWithSuffix, classInSamePackageAsResource); libraryNameWithSuffix, classInSamePackageAsResource);
System.load(fullLibraryNameWithPath); System.load(fullLibraryNameWithPath);

View File

@@ -5,24 +5,30 @@ import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComException; import com.jacob.com.ComException;
/** /**
* This test verifies patch SF 1794811 . * This test verifies patch SF 1794811 . It shows how unicode filenames throw
* It shows how unicode filenames throw exceptions in 1.13M4 and earlier. * exceptions in 1.13M4 and earlier.
*
* @author justme84 * @author justme84
* *
*/ */
public class UnicodeErrorTest extends BaseTestCase { public class UnicodeErrorTest extends BaseTestCase {
/**
* verifies that messages can now have unicode in them like when the file
* names have unicode characters
*/
public void testUnicodeCharactersInErrorMessage() { public void testUnicodeCharactersInErrorMessage() {
ActiveXComponent application = new ActiveXComponent("Word.Application"); ActiveXComponent application = new ActiveXComponent("Word.Application");
ActiveXComponent documents = application.getPropertyAsComponent("Documents"); ActiveXComponent documents = application
.getPropertyAsComponent("Documents");
String fileName = "abc\u0411\u0412\u0413\u0414def"; String fileName = "abc\u0411\u0412\u0413\u0414def";
try { try {
documents.invoke("Open", fileName); documents.invoke("Open", fileName);
fail("Should have thrown an exception"); fail("Should have thrown an exception");
} catch (ComException e) { } catch (ComException e) {
assertTrue("Error message should contain file name with unicode " + assertTrue("Error message should contain file name with unicode "
"characters in it. "+e.getMessage(), + "characters in it. " + e.getMessage(), e.getMessage()
e.getMessage().indexOf(fileName) > 0); .indexOf(fileName) > 0);
} }
} }
} }

View File

@@ -2,6 +2,7 @@ package com.jacob.test.events;
import com.jacob.activeX.ActiveXComponent; import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComException; import com.jacob.com.ComException;
import com.jacob.com.ComThread;
import com.jacob.com.Dispatch; import com.jacob.com.Dispatch;
import com.jacob.com.DispatchEvents; import com.jacob.com.DispatchEvents;
import com.jacob.com.InvocationProxy; import com.jacob.com.InvocationProxy;
@@ -11,40 +12,33 @@ import com.jacob.test.BaseTestCase;
/** /**
* This test was lifted from a forum posting and shows how you can't listen to * This test was lifted from a forum posting and shows how you can't listen to
* Excel events (added post 1.9.1 Eclipse Settings.) This also uses the 1.9.1 * Excel events (added post 1.9.1 Eclipse Settings.) This also uses the 1.9.1
* InvocationProxy to receive the events. * InvocationProxy to receive the events. The test was modified in 1.14 to show
* how to hook up multiple event listeners to various Excel components
* <p> * <p>
* May need to run with some command line options (including from inside Eclipse). * May need to run with some command line options (including from inside
* Look in the docs area at the Jacob usage document for command line options. * Eclipse). Look in the docs area at the Jacob usage document for command line
* options.
*/ */
public class ExcelEventTest extends BaseTestCase { public class ExcelEventTest extends BaseTestCase {
/** /**
* load up excel, register for events and make stuff happen * load up excel, register for events and make stuff happen
*
* @param args * @param args
*/ */
public void testExcelWithInvocationProxy() { public void testExcelWithInvocationProxy() {
String pid = "Excel.Application"; ComThread.InitSTA();
// we are going to listen to events on Application.
// You can probably also listen Excel.Sheet and Excel.Chart
String excelApplicationProgramId = "Excel.Application";
String excelSheetProgramId = "Excel.Sheet";
String typeLibLocation = "C:\\Program Files\\Microsoft Office\\OFFICE11\\EXCEL.EXE"; String typeLibLocation = "C:\\Program Files\\Microsoft Office\\OFFICE11\\EXCEL.EXE";
// Grab The Component. // Grab The Component.
ActiveXComponent axc = new ActiveXComponent(pid); ActiveXComponent axc = new ActiveXComponent(excelApplicationProgramId);
try { hookupListener(axc, excelApplicationProgramId, typeLibLocation);
// Add a listener (doesn't matter what it is).
DispatchEvents de;
if (typeLibLocation == null) {
de = new DispatchEvents(axc, new ExcelEvents());
} else {
de = new DispatchEvents(axc, new ExcelEvents(), pid,
typeLibLocation);
}
if (de == null) {
System.out
.println("No exception thrown but no dispatch returned for Excel events");
} else {
// Yea!
System.out.println("Successfully attached to " + pid);
} try {
System.out.println("version=" + axc.getProperty("Version")); System.out.println("version=" + axc.getProperty("Version"));
System.out.println("version=" + Dispatch.get(axc, "Version")); System.out.println("version=" + Dispatch.get(axc, "Version"));
@@ -52,6 +46,7 @@ public class ExcelEventTest extends BaseTestCase {
Dispatch workbooks = axc.getPropertyAsComponent("Workbooks"); Dispatch workbooks = axc.getPropertyAsComponent("Workbooks");
Dispatch workbook = Dispatch.get(workbooks, "Add").toDispatch(); Dispatch workbook = Dispatch.get(workbooks, "Add").toDispatch();
Dispatch sheet = Dispatch.get(workbook, "ActiveSheet").toDispatch(); Dispatch sheet = Dispatch.get(workbook, "ActiveSheet").toDispatch();
hookupListener(sheet, excelSheetProgramId, typeLibLocation);
Dispatch a1 = Dispatch.invoke(sheet, "Range", Dispatch.Get, Dispatch a1 = Dispatch.invoke(sheet, "Range", Dispatch.Get,
new Object[] { "A1" }, new int[1]).toDispatch(); new Object[] { "A1" }, new int[1]).toDispatch();
Dispatch a2 = Dispatch.invoke(sheet, "Range", Dispatch.Get, Dispatch a2 = Dispatch.invoke(sheet, "Range", Dispatch.Get,
@@ -60,34 +55,81 @@ public class ExcelEventTest extends BaseTestCase {
System.out.println("Inserting calculation 2xA1 into A2"); System.out.println("Inserting calculation 2xA1 into A2");
Dispatch.put(a1, "Value", "123.456"); Dispatch.put(a1, "Value", "123.456");
Dispatch.put(a2, "Formula", "=A1*2"); Dispatch.put(a2, "Formula", "=A1*2");
System.out.println("Retrieved a1 from excel:" + Dispatch.get(a1, "Value")); System.out.println("Retrieved a1 from excel:"
System.out.println("Retrieved a2 from excel:" + Dispatch.get(a2, "Value")); + Dispatch.get(a1, "Value"));
System.out.println("Retrieved a2 from excel:"
+ Dispatch.get(a2, "Value"));
Variant f = new Variant(false); Variant f = new Variant(false);
Dispatch.call(workbook, "Close", f); Dispatch.call(workbook, "Close", f);
axc.invoke("Quit", new Variant[] {}); axc.invoke("Quit", new Variant[] {});
} catch (ComException cfe) { } catch (ComException cfe) {
cfe.printStackTrace(); cfe.printStackTrace();
fail("Failed to attach to " + pid + ": " fail("Failed to attach to " + excelApplicationProgramId + ": "
+ cfe.getMessage()); + cfe.getMessage());
}
try {
// the sleep is required to let everything clear out after the quit
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ComThread.Release();
}
/**
* extracted the listener hookup so we could try multiple listeners.
*
* @param axc
* @param programId
* @param typeLibLocation
*/
private void hookupListener(Dispatch axc, String programId,
String typeLibLocation) {
// Add a listener (doesn't matter what it is).
DispatchEvents applicationEvents;
if (typeLibLocation == null) {
applicationEvents = new DispatchEvents(axc, new ExcelEvents(
programId));
} else {
applicationEvents = new DispatchEvents(axc, new ExcelEvents(
programId), programId, typeLibLocation);
}
if (applicationEvents == null) {
System.out
.println("No exception thrown but no dispatch returned for Excel events");
} else {
// Yea!
System.out.println("Successfully attached to " + programId);
} }
} }
/**
* Proxy class to verify we receive expected events
*/
public class ExcelEvents extends InvocationProxy { public class ExcelEvents extends InvocationProxy {
private String listenerPrefix = "-";
/** /**
* Constructor so we can create an instance that implements invoke() * Constructor so we can create an instance that implements invoke()
*
* @param interfaceIdentifier
* a string that identifies which listener is speaking
*/ */
public ExcelEvents() { public ExcelEvents(String interfaceIdentifier) {
listenerPrefix = interfaceIdentifier;
} }
/** /**
* Override the invoke method to log all the events so that we don't have to * Override the invoke method to log all the events so that we don't
* implement all of the specific events. * have to implement all of the specific events.
*/ */
public Variant invoke(String methodName, Variant targetParameter[]) { public Variant invoke(String methodName, Variant targetParameter[]) {
System.out.println("Received event from Windows program" + methodName); System.out.println("Received event from " + listenerPrefix + ": "
+ methodName);
return null; return null;
} }

View File

@@ -6,21 +6,25 @@ import com.jacob.com.Dispatch;
import com.jacob.com.DispatchEvents; import com.jacob.com.DispatchEvents;
import com.jacob.com.Variant; import com.jacob.com.Variant;
import com.jacob.test.BaseTestCase; import com.jacob.test.BaseTestCase;
/** /**
* This test runs fine against jdk 1.4 and 1.5 * This test runs fine against jdk 1.4 and 1.5
* *
* This demonstrates the new event handling code in jacob 1.7 * This demonstrates the new event handling code in jacob 1.7 This example will
* This example will open up IE and print out some of the events * open up IE and print out some of the events it listens to as it havigates to
* it listens to as it havigates to web sites. * web sites. contributed by Niels Olof Bouvin mailto:n.o.bouvin@daimi.au.dk and
* contributed by Niels Olof Bouvin mailto:n.o.bouvin@daimi.au.dk * Henning Jae jehoej@daimi.au.dk
* and Henning Jae jehoej@daimi.au.dk
* <p> * <p>
* May need to run with some command line options (including from inside Eclipse). * May need to run with some command line options (including from inside
* Look in the docs area at the Jacob usage document for command line options. * Eclipse). Look in the docs area at the Jacob usage document for command line
* options.
*/ */
public class IETest extends BaseTestCase { public class IETest extends BaseTestCase {
/**
* runs the IE test and feeds it commands
*/
public void testRunIE() { public void testRunIE() {
// this line starts the pump but it runs fine without it // this line starts the pump but it runs fine without it
ComThread.startMainSTA(); ComThread.startMainSTA();
@@ -36,7 +40,8 @@ public class IETest extends BaseTestCase {
// e.printStackTrace(); // e.printStackTrace();
} }
} }
System.out.println("Main: Thread quit, about to quit main sta in thread " System.out
.println("Main: Thread quit, about to quit main sta in thread "
+ Thread.currentThread().getName()); + Thread.currentThread().getName());
// this line only does someting if startMainSTA() was called // this line only does someting if startMainSTA() was called
ComThread.quitMainSTA(); ComThread.quitMainSTA();
@@ -44,13 +49,14 @@ public class IETest extends BaseTestCase {
+ Thread.currentThread().getName()); + Thread.currentThread().getName());
if (aThread.threadFailedWithException != null) { if (aThread.threadFailedWithException != null) {
fail("caught an unexpected exception "+aThread.threadFailedWithException); fail("caught an unexpected exception "
+ aThread.threadFailedWithException);
} }
} }
} }
class IETestThread extends Thread class IETestThread extends Thread {
{ /** flag that says we got a quit message from IE */
public static boolean quitHandled = false; public static boolean quitHandled = false;
/** /**
@@ -58,17 +64,20 @@ class IETestThread extends Thread
*/ */
public Throwable threadFailedWithException = null; public Throwable threadFailedWithException = null;
/**
* constructor for the test thread
*/
public IETestThread() { public IETestThread() {
super(); super();
} }
public void run() public void run() {
{
// this used to be 5 seconds but sourceforge is slow // this used to be 5 seconds but sourceforge is slow
int delay = 5000; // msec int delay = 5000; // msec
// paired with statement below that blows up // paired with statement below that blows up
ComThread.InitMTA(); ComThread.InitMTA();
ActiveXComponent ie = new ActiveXComponent("InternetExplorer.Application"); ActiveXComponent ie = new ActiveXComponent(
"InternetExplorer.Application");
try { try {
Dispatch.put(ie, "Visible", new Variant(true)); Dispatch.put(ie, "Visible", new Variant(true));
Dispatch.put(ie, "AddressBar", new Variant(true)); Dispatch.put(ie, "AddressBar", new Variant(true));
@@ -83,14 +92,24 @@ class IETestThread extends Thread
Variant optional = new Variant(); Variant optional = new Variant();
optional.putNoParam(); optional.putNoParam();
System.out.println("IETestThread: About to call navigate to sourceforge"); System.out
Dispatch.call(ie, "Navigate", new Variant("http://sourceforge.net/projects/jacob-project")); .println("IETestThread: About to call navigate to sourceforge");
System.out.println("IETestThread: Did call navigate to sourceforge"); Dispatch.call(ie, "Navigate", new Variant(
try { Thread.sleep(delay); } catch (Exception e) {} "http://sourceforge.net/projects/jacob-project"));
System.out
.println("IETestThread: Did call navigate to sourceforge");
try {
Thread.sleep(delay);
} catch (Exception e) {
}
System.out.println("IETestThread: About to call navigate to yahoo"); System.out.println("IETestThread: About to call navigate to yahoo");
Dispatch.call(ie, "Navigate", new Variant("http://groups.yahoo.com/group/jacob-project")); Dispatch.call(ie, "Navigate", new Variant(
"http://groups.yahoo.com/group/jacob-project"));
System.out.println("IETestThread: Did call navigate to yahoo"); System.out.println("IETestThread: Did call navigate to yahoo");
try { Thread.sleep(delay); } catch (Exception e) {} try {
Thread.sleep(delay);
} catch (Exception e) {
}
} catch (Exception e) { } catch (Exception e) {
threadFailedWithException = e; threadFailedWithException = e;
e.printStackTrace(); e.printStackTrace();
@@ -105,112 +124,287 @@ class IETestThread extends Thread
// this blows up when it tries to release a DispatchEvents object // this blows up when it tries to release a DispatchEvents object
// I think this is because there is still one event we should get back // I think this is because there is still one event we should get back
// "OnQuit" that will came after we have released the thread pool // "OnQuit" that will came after we have released the thread pool
// this is probably messed up because DispatchEvent object will have been // this is probably messed up because DispatchEvent object will have
// been
// freed before the callback // freed before the callback
// commenting out ie.invoke(quit...) causes this to work without error // commenting out ie.invoke(quit...) causes this to work without error
// this code tries to wait until the quit has been handled but that doesn't work // this code tries to wait until the quit has been handled but that
System.out.println("IETestThread: Waiting until we've received the quit callback"); // doesn't work
System.out
.println("IETestThread: Waiting until we've received the quit callback");
while (!quitHandled) { while (!quitHandled) {
try { Thread.sleep(delay/5);} catch (InterruptedException e) {} try {
Thread.sleep(delay / 5);
} catch (InterruptedException e) {
}
} }
System.out.println("IETestThread: Received the quit callback"); System.out.println("IETestThread: Received the quit callback");
// wait a little while for it to end // wait a little while for it to end
// try {Thread.sleep(delay); } catch (InterruptedException e) {} // try {Thread.sleep(delay); } catch (InterruptedException e) {}
System.out.println("IETestThread: about to call ComThread.Release in thread " + System.out
Thread.currentThread().getName()); .println("IETestThread: about to call ComThread.Release in thread "
+ Thread.currentThread().getName());
ComThread.Release(); ComThread.Release();
} }
/** /**
* The events class must be publicly accessable for reflection to work. * The events class must be publicly accessable for reflection to work. The
* The list of available events is located at http://msdn2.microsoft.com/en-us/library/aa768280.aspx * list of available events is located at
* http://msdn2.microsoft.com/en-us/library/aa768280.aspx
*/
public class IEEvents {
/**
* Internet explorer event this proxy can receive
*
* @param args
* the COM Variant objects that this event passes in.
*/ */
public class IEEvents
{
public void BeforeNavigate2(Variant[] args) { public void BeforeNavigate2(Variant[] args) {
System.out.println("IEEvents Received ("+Thread.currentThread().getName()+"): BeforeNavigate2 "+args.length); System.out.println("IEEvents Received ("
+ Thread.currentThread().getName() + "): BeforeNavigate2 "
+ args.length);
} }
/**
* Internet explorer event this proxy can receive
*
* @param args
* the COM Variant objects that this event passes in.
*/
public void CommandStateChange(Variant[] args) { public void CommandStateChange(Variant[] args) {
System.out.println("IEEvents Received ("+Thread.currentThread().getName()+"): CommandStateChange "+args.length); System.out.println("IEEvents Received ("
+ Thread.currentThread().getName()
+ "): CommandStateChange " + args.length);
} }
/**
* Internet explorer event this proxy can receive
*
* @param args
* the COM Variant objects that this event passes in.
*/
public void DocumentComplete(Variant[] args) { public void DocumentComplete(Variant[] args) {
System.out.println("IEEvents Received ("+Thread.currentThread().getName()+"): DocumentComplete "+args.length); System.out.println("IEEvents Received ("
+ Thread.currentThread().getName() + "): DocumentComplete "
+ args.length);
} }
/**
* Internet explorer event this proxy can receive
*
* @param args
* the COM Variant objects that this event passes in.
*/
public void DownloadBegin(Variant[] args) { public void DownloadBegin(Variant[] args) {
System.out.println("IEEvents Received ("+Thread.currentThread().getName()+"): DownloadBegin "+args.length); System.out.println("IEEvents Received ("
+ Thread.currentThread().getName() + "): DownloadBegin "
+ args.length);
} }
/**
* Internet explorer event this proxy can receive
*
* @param args
* the COM Variant objects that this event passes in.
*/
public void DownloadComplete(Variant[] args) { public void DownloadComplete(Variant[] args) {
System.out.println("IEEvents Received ("+Thread.currentThread().getName()+"): DownloadComplete "+args.length); System.out.println("IEEvents Received ("
+ Thread.currentThread().getName() + "): DownloadComplete "
+ args.length);
} }
/**
* Internet explorer event this proxy can receive
*
* @param args
* the COM Variant objects that this event passes in.
*/
public void NavigateError(Variant[] args) { public void NavigateError(Variant[] args) {
System.out.println("IEEvents Received ("+Thread.currentThread().getName()+"): NavigateError "+args.length); System.out.println("IEEvents Received ("
+ Thread.currentThread().getName() + "): NavigateError "
+ args.length);
} }
/**
* Internet explorer event this proxy can receive
*
* @param args
* the COM Variant objects that this event passes in.
*/
public void NavigateComplete2(Variant[] args) { public void NavigateComplete2(Variant[] args) {
System.out.println("IEEvents Received ("+Thread.currentThread().getName()+"): NavigateComplete "+args.length); System.out.println("IEEvents Received ("
+ Thread.currentThread().getName() + "): NavigateComplete "
+ args.length);
} }
/**
* Internet explorer event this proxy can receive
*
* @param args
* the COM Variant objects that this event passes in.
*/
public void NewWindow2(Variant[] args) { public void NewWindow2(Variant[] args) {
System.out.println("IEEvents Received ("+Thread.currentThread().getName()+"): NewWindow2 "+args.length); System.out.println("IEEvents Received ("
+ Thread.currentThread().getName() + "): NewWindow2 "
+ args.length);
} }
/**
* Internet explorer event this proxy can receive
*
* @param args
* the COM Variant objects that this event passes in.
*/
public void OnFullScreen(Variant[] args) { public void OnFullScreen(Variant[] args) {
System.out.println("IEEvents Received ("+Thread.currentThread().getName()+"): OnFullScreen "+args.length); System.out.println("IEEvents Received ("
+ Thread.currentThread().getName() + "): OnFullScreen "
+ args.length);
} }
/**
* Internet explorer event this proxy can receive
*
* @param args
* the COM Variant objects that this event passes in.
*/
public void OnMenuBar(Variant[] args) { public void OnMenuBar(Variant[] args) {
System.out.println("IEEvents Received ("+Thread.currentThread().getName()+"): OnMenuBar "+args.length); System.out.println("IEEvents Received ("
+ Thread.currentThread().getName() + "): OnMenuBar "
+ args.length);
} }
/**
* Internet explorer event this proxy can receive
*
* @param args
* the COM Variant objects that this event passes in.
*/
public void OnQuit(Variant[] args) { public void OnQuit(Variant[] args) {
System.out.println("IEEvents Received ("+Thread.currentThread().getName()+"): OnQuit "+args.length); System.out.println("IEEvents Received ("
+ Thread.currentThread().getName() + "): OnQuit "
+ args.length);
IETestThread.quitHandled = true; IETestThread.quitHandled = true;
} }
/**
* Internet explorer event this proxy can receive
*
* @param args
* the COM Variant objects that this event passes in.
*/
public void OnStatusBar(Variant[] args) { public void OnStatusBar(Variant[] args) {
System.out.println("IEEvents Received ("+Thread.currentThread().getName()+"): OnStatusBar "+args.length); System.out.println("IEEvents Received ("
+ Thread.currentThread().getName() + "): OnStatusBar "
+ args.length);
} }
/**
* Internet explorer event this proxy can receive
*
* @param args
* the COM Variant objects that this event passes in.
*/
public void OnTheaterMode(Variant[] args) { public void OnTheaterMode(Variant[] args) {
System.out.println("IEEvents Received ("+Thread.currentThread().getName()+"): OnTheaterMode "+args.length); System.out.println("IEEvents Received ("
+ Thread.currentThread().getName() + "): OnTheaterMode "
+ args.length);
} }
/**
* Internet explorer event this proxy can receive
*
* @param args
* the COM Variant objects that this event passes in.
*/
public void OnToolBar(Variant[] args) { public void OnToolBar(Variant[] args) {
System.out.println("IEEvents Received ("+Thread.currentThread().getName()+"): OnToolBar "+args.length); System.out.println("IEEvents Received ("
+ Thread.currentThread().getName() + "): OnToolBar "
+ args.length);
} }
/**
* Internet explorer event this proxy can receive
*
* @param args
* the COM Variant objects that this event passes in.
*/
public void OnVisible(Variant[] args) { public void OnVisible(Variant[] args) {
System.out.println("IEEvents Received ("+Thread.currentThread().getName()+"): OnVisible "+args.length); System.out.println("IEEvents Received ("
+ Thread.currentThread().getName() + "): OnVisible "
+ args.length);
} }
/**
* Internet explorer event this proxy can receive
*
* @param args
* the COM Variant objects that this event passes in.
*/
public void ProgressChange(Variant[] args) { public void ProgressChange(Variant[] args) {
System.out.println("IEEvents Received ("+Thread.currentThread().getName()+"): ProgressChange "+args.length); System.out.println("IEEvents Received ("
+ Thread.currentThread().getName() + "): ProgressChange "
+ args.length);
} }
/**
* Internet explorer event this proxy can receive
*
* @param args
* the COM Variant objects that this event passes in.
*/
public void PropertyChange(Variant[] args) { public void PropertyChange(Variant[] args) {
System.out.println("IEEvents Received ("+Thread.currentThread().getName()+"): PropertyChange "+args.length); System.out.println("IEEvents Received ("
+ Thread.currentThread().getName() + "): PropertyChange "
+ args.length);
} }
/**
* Internet explorer event this proxy can receive
*
* @param args
* the COM Variant objects that this event passes in.
*/
public void SetSecureLockIcon(Variant[] args) { public void SetSecureLockIcon(Variant[] args) {
System.out.println("IEEvents Received ("+Thread.currentThread().getName()+"): setSecureLockIcon "+args.length); System.out.println("IEEvents Received ("
+ Thread.currentThread().getName()
+ "): setSecureLockIcon " + args.length);
} }
/**
* Internet explorer event this proxy can receive
*
* @param args
* the COM Variant objects that this event passes in.
*/
public void StatusTextChange(Variant[] args) { public void StatusTextChange(Variant[] args) {
System.out.println("IEEvents Received ("+Thread.currentThread().getName()+"): StatusTextChange "+args.length); System.out.println("IEEvents Received ("
+ Thread.currentThread().getName() + "): StatusTextChange "
+ args.length);
} }
/**
* Internet explorer event this proxy can receive
*
* @param args
* the COM Variant objects that this event passes in.
*/
public void TitleChange(Variant[] args) { public void TitleChange(Variant[] args) {
System.out.println("IEEvents Received ("+Thread.currentThread().getName()+"): TitleChange "+args.length); System.out.println("IEEvents Received ("
+ Thread.currentThread().getName() + "): TitleChange "
+ args.length);
} }
/**
* Internet explorer event this proxy can receive
*
* @param args
* the COM Variant objects that this event passes in.
*/
public void WindowClosing(Variant[] args) { public void WindowClosing(Variant[] args) {
System.out.println("IEEvents Received ("+Thread.currentThread().getName()+"): WindowClosing "+args.length); System.out.println("IEEvents Received ("
+ Thread.currentThread().getName() + "): WindowClosing "
+ args.length);
} }
} }

View File

@@ -6,22 +6,25 @@ import com.jacob.com.ComThread;
import com.jacob.com.Dispatch; import com.jacob.com.Dispatch;
import com.jacob.com.Variant; import com.jacob.com.Variant;
import com.jacob.test.BaseTestCase; import com.jacob.test.BaseTestCase;
/** /**
* This test runs fine against jdk 1.4 and 1.5 * This test runs fine against jdk 1.4 and 1.5
* *
* This demonstrates the new event handling code in jacob 1.7 * This demonstrates the new event handling code in jacob 1.7 This example will
* This example will open up IE and print out some of the events * open up IE and print out some of the events it listens to as it havigates to
* it listens to as it havigates to web sites. * web sites. contributed by Niels Olof Bouvin mailto:n.o.bouvin@daimi.au.dk and
* contributed by Niels Olof Bouvin mailto:n.o.bouvin@daimi.au.dk * Henning Jae jehoej@daimi.au.dk
* and Henning Jae jehoej@daimi.au.dk
* <p> * <p>
* May need to run with some command line options (including from inside Eclipse). * May need to run with some command line options (including from inside
* Look in the docs area at the Jacob usage document for command line options. * Eclipse). Look in the docs area at the Jacob usage document for command line
* options.
*/ */
public class IETestActiveXProxy extends BaseTestCase { public class IETestActiveXProxy extends BaseTestCase {
/**
* the main test method that builds up the connection and runs the test
*/
public void testIEActiveProxyCallback() { public void testIEActiveProxyCallback() {
// this line starts the pump but it runs fine without it // this line starts the pump but it runs fine without it
ComThread.startMainSTA(); ComThread.startMainSTA();
@@ -37,20 +40,22 @@ public class IETestActiveXProxy extends BaseTestCase {
// e.printStackTrace(); // e.printStackTrace();
} }
} }
System.out.println("Main: Thread quit, about to quit main sta in thread " System.out
.println("Main: Thread quit, about to quit main sta in thread "
+ Thread.currentThread().getName()); + Thread.currentThread().getName());
// this line only does someting if startMainSTA() was called // this line only does someting if startMainSTA() was called
ComThread.quitMainSTA(); ComThread.quitMainSTA();
System.out.println("Main: did quit main sta in thread " System.out.println("Main: did quit main sta in thread "
+ Thread.currentThread().getName()); + Thread.currentThread().getName());
if (aThread.threadFailedWithException != null) { if (aThread.threadFailedWithException != null) {
fail("caught an unexpected exception "+aThread.threadFailedWithException); fail("caught an unexpected exception "
+ aThread.threadFailedWithException);
} }
} }
} }
class IETestActiveProxyThread extends Thread class IETestActiveProxyThread extends Thread {
{ /** says that the quit message has been received from the target application */
public static boolean quitHandled = false; public static boolean quitHandled = false;
/** /**
@@ -58,39 +63,55 @@ class IETestActiveProxyThread extends Thread
*/ */
public Throwable threadFailedWithException = null; public Throwable threadFailedWithException = null;
/** the thread's constructor */
public IETestActiveProxyThread() { public IETestActiveProxyThread() {
super(); super();
} }
public void run() public void run() {
{
// this used to be 5 seconds but sourceforge is slow // this used to be 5 seconds but sourceforge is slow
int delay = 5000; // msec int delay = 5000; // msec
// paired with statement below that blows up // paired with statement below that blows up
ComThread.InitMTA(); ComThread.InitMTA();
ActiveXComponent ie = new ActiveXComponent("InternetExplorer.Application"); ActiveXComponent ie = new ActiveXComponent(
"InternetExplorer.Application");
try { try {
Dispatch.put(ie, "Visible", new Variant(true)); Dispatch.put(ie, "Visible", new Variant(true));
Dispatch.put(ie, "AddressBar", new Variant(true)); Dispatch.put(ie, "AddressBar", new Variant(true));
System.out.println("IETestActiveProxyThread: " + Dispatch.get(ie, "Path")); System.out.println("IETestActiveProxyThread: "
+ Dispatch.get(ie, "Path"));
Dispatch.put(ie, "StatusText", new Variant("My Status Text")); Dispatch.put(ie, "StatusText", new Variant("My Status Text"));
System.out.println("IETestActiveProxyThread: About to hookup event listener"); System.out
.println("IETestActiveProxyThread: About to hookup event listener");
IEEventsActiveProxy ieE = new IEEventsActiveProxy(); IEEventsActiveProxy ieE = new IEEventsActiveProxy();
new ActiveXDispatchEvents(ie, ieE, "InternetExplorer.Application.1"); new ActiveXDispatchEvents(ie, ieE, "InternetExplorer.Application.1");
System.out.println("IETestActiveProxyThread: Did hookup event listener"); System.out
.println("IETestActiveProxyThread: Did hookup event listener");
// / why is this here? Was there some other code here in the past? // / why is this here? Was there some other code here in the past?
Variant optional = new Variant(); Variant optional = new Variant();
optional.putNoParam(); optional.putNoParam();
System.out.println("IETestActiveProxyThread: About to call navigate to sourceforge"); System.out
Dispatch.call(ie, "Navigate", new Variant("http://sourceforge.net/projects/jacob-project")); .println("IETestActiveProxyThread: About to call navigate to sourceforge");
System.out.println("IETestActiveProxyThread: Did call navigate to sourceforge"); Dispatch.call(ie, "Navigate", new Variant(
try { Thread.sleep(delay); } catch (Exception e) {} "http://sourceforge.net/projects/jacob-project"));
System.out.println("IETestActiveProxyThread: About to call navigate to yahoo"); System.out
Dispatch.call(ie, "Navigate", new Variant("http://groups.yahoo.com/group/jacob-project")); .println("IETestActiveProxyThread: Did call navigate to sourceforge");
System.out.println("IETestActiveProxyThread: Did call navigate to yahoo"); try {
try { Thread.sleep(delay); } catch (Exception e) {} Thread.sleep(delay);
} catch (Exception e) {
}
System.out
.println("IETestActiveProxyThread: About to call navigate to yahoo");
Dispatch.call(ie, "Navigate", new Variant(
"http://groups.yahoo.com/group/jacob-project"));
System.out
.println("IETestActiveProxyThread: Did call navigate to yahoo");
try {
Thread.sleep(delay);
} catch (Exception e) {
}
} catch (Exception e) { } catch (Exception e) {
threadFailedWithException = e; threadFailedWithException = e;
e.printStackTrace(); e.printStackTrace();
@@ -105,113 +126,163 @@ class IETestActiveProxyThread extends Thread
// this blows up when it tries to release a DispatchEvents object // this blows up when it tries to release a DispatchEvents object
// I think this is because there is still one event we should get back // I think this is because there is still one event we should get back
// "OnQuit" that will came after we have released the thread pool // "OnQuit" that will came after we have released the thread pool
// this is probably messed up because DispatchEvent object will have been // this is probably messed up because DispatchEvent object will have
// been
// freed before the callback // freed before the callback
// commenting out ie.invoke(quit...) causes this to work without error // commenting out ie.invoke(quit...) causes this to work without error
// this code tries to wait until the quit has been handled but that doesn't work // this code tries to wait until the quit has been handled but that
System.out.println("IETestActiveProxyThread: Waiting until we've received the quit callback"); // doesn't work
System.out
.println("IETestActiveProxyThread: Waiting until we've received the quit callback");
while (!quitHandled) { while (!quitHandled) {
try { Thread.sleep(delay/5);} catch (InterruptedException e) {} try {
Thread.sleep(delay / 5);
} catch (InterruptedException e) {
} }
System.out.println("IETestActiveProxyThread: Received the quit callback"); }
System.out
.println("IETestActiveProxyThread: Received the quit callback");
// wait a little while for it to end // wait a little while for it to end
// try {Thread.sleep(delay); } catch (InterruptedException e) {} // try {Thread.sleep(delay); } catch (InterruptedException e) {}
System.out.println("IETestActiveProxyThread: about to call ComThread.Release in thread " + System.out
Thread.currentThread().getName()); .println("IETestActiveProxyThread: about to call ComThread.Release in thread "
+ Thread.currentThread().getName());
ComThread.Release(); ComThread.Release();
} }
/** /**
* The events class must be publicly accessable for reflection to work. * The events class must be publicly accessable for reflection to work. The
* The list of available events is located at http://msdn2.microsoft.com/en-us/library/aa768280.aspx * list of available events is located at
* http://msdn2.microsoft.com/en-us/library/aa768280.aspx
*/ */
public class IEEventsActiveProxy public class IEEventsActiveProxy {
{
public void BeforeNavigate2(Dispatch pDisp, String url, Integer flags, public void BeforeNavigate2(Dispatch pDisp, String url, Integer flags,
String targetFrameName, Variant postData, String headers, Boolean cancel) { String targetFrameName, Variant postData, String headers,
System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): BeforeNavigate2 "+url); Boolean cancel) {
System.out.println("IEEventsActiveProxy Received ("
+ Thread.currentThread().getName() + "): BeforeNavigate2 "
+ url);
} }
public void CommandStateChange(Integer command, Boolean enable) { public void CommandStateChange(Integer command, Boolean enable) {
System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): CommandStateChange "+command); System.out.println("IEEventsActiveProxy Received ("
+ Thread.currentThread().getName()
+ "): CommandStateChange " + command);
} }
public void DocumentComplete(Dispatch pDisp, String url) { public void DocumentComplete(Dispatch pDisp, String url) {
System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): DocumentComplete "+url); System.out.println("IEEventsActiveProxy Received ("
+ Thread.currentThread().getName() + "): DocumentComplete "
+ url);
} }
public void DownloadBegin() { public void DownloadBegin() {
System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): DownloadBegin "); System.out.println("IEEventsActiveProxy Received ("
+ Thread.currentThread().getName() + "): DownloadBegin ");
} }
public void DownloadComplete() { public void DownloadComplete() {
System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): DownloadComplete "); System.out
.println("IEEventsActiveProxy Received ("
+ Thread.currentThread().getName()
+ "): DownloadComplete ");
} }
public void NavigateComplete2(Dispatch pDisp, String url) { public void NavigateComplete2(Dispatch pDisp, String url) {
System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): NavigateComplete "+url); System.out.println("IEEventsActiveProxy Received ("
+ Thread.currentThread().getName() + "): NavigateComplete "
+ url);
} }
public void NavigateError(Dispatch pDispatch, String url, String targetFrameName, Integer statusCode, Boolean Cancel) { public void NavigateError(Dispatch pDispatch, String url,
System.out.println("IEEvents Received ("+Thread.currentThread().getName()+"): NavigateError "+statusCode); String targetFrameName, Integer statusCode, Boolean Cancel) {
System.out.println("IEEvents Received ("
+ Thread.currentThread().getName() + "): NavigateError "
+ statusCode);
} }
public void NewWindow2(Dispatch pDisp, Boolean cancel) { public void NewWindow2(Dispatch pDisp, Boolean cancel) {
System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): NewWindow2 "+pDisp); System.out.println("IEEventsActiveProxy Received ("
+ Thread.currentThread().getName() + "): NewWindow2 "
+ pDisp);
} }
public void OnFullScreen(Boolean fullScreen) { public void OnFullScreen(Boolean fullScreen) {
System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): OnFullScreen "+fullScreen); System.out.println("IEEventsActiveProxy Received ("
+ Thread.currentThread().getName() + "): OnFullScreen "
+ fullScreen);
} }
public void OnMenuBar(Boolean menuBar) { public void OnMenuBar(Boolean menuBar) {
System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): OnMenuBar "+menuBar); System.out.println("IEEventsActiveProxy Received ("
+ Thread.currentThread().getName() + "): OnMenuBar "
+ menuBar);
} }
public void OnQuit() { public void OnQuit() {
System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): OnQuit "); System.out.println("IEEventsActiveProxy Received ("
+ Thread.currentThread().getName() + "): OnQuit ");
IETestActiveProxyThread.quitHandled = true; IETestActiveProxyThread.quitHandled = true;
} }
public void OnStatusBar(Boolean statusBar) { public void OnStatusBar(Boolean statusBar) {
System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): OnStatusBar "+statusBar); System.out.println("IEEventsActiveProxy Received ("
+ Thread.currentThread().getName() + "): OnStatusBar "
+ statusBar);
} }
public void OnTheaterMode(Boolean theaterMode) { public void OnTheaterMode(Boolean theaterMode) {
System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): OnTheaterMode "+theaterMode); System.out.println("IEEventsActiveProxy Received ("
+ Thread.currentThread().getName() + "): OnTheaterMode "
+ theaterMode);
} }
public void OnToolBar(Boolean onToolBar) { public void OnToolBar(Boolean onToolBar) {
System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): OnToolBar "+onToolBar); System.out.println("IEEventsActiveProxy Received ("
+ Thread.currentThread().getName() + "): OnToolBar "
+ onToolBar);
} }
public void OnVisible(Boolean onVisible) { public void OnVisible(Boolean onVisible) {
System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): onVisible "+ onVisible); System.out.println("IEEventsActiveProxy Received ("
+ Thread.currentThread().getName() + "): onVisible "
+ onVisible);
} }
public void ProgressChange() { public void ProgressChange() {
System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): ProgressChange "); System.out.println("IEEventsActiveProxy Received ("
+ Thread.currentThread().getName() + "): ProgressChange ");
} }
public void PropertyChange() { public void PropertyChange() {
System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): PropertyChange "); System.out.println("IEEventsActiveProxy Received ("
+ Thread.currentThread().getName() + "): PropertyChange ");
} }
public void SetSecureLockIcon(Integer secureLockIcon) { public void SetSecureLockIcon(Integer secureLockIcon) {
System.out.println("IEEvents Received ("+Thread.currentThread().getName()+"): setSecureLockIcon "+secureLockIcon); System.out.println("IEEvents Received ("
+ Thread.currentThread().getName()
+ "): setSecureLockIcon " + secureLockIcon);
} }
public void StatusTextChange() { public void StatusTextChange() {
System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): StatusTextChange "); System.out
.println("IEEventsActiveProxy Received ("
+ Thread.currentThread().getName()
+ "): StatusTextChange ");
} }
public void TitleChange() { public void TitleChange() {
System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): TitleChange "); System.out.println("IEEventsActiveProxy Received ("
+ Thread.currentThread().getName() + "): TitleChange ");
} }
public void WindowClosing(Boolean isChildWindow) { public void WindowClosing(Boolean isChildWindow) {
System.out.println("IEEvents Received ("+Thread.currentThread().getName()+"): WindowClosing "+isChildWindow); System.out.println("IEEvents Received ("
+ Thread.currentThread().getName() + "): WindowClosing "
+ isChildWindow);
} }
} }

View File

@@ -9,19 +9,20 @@ import com.jacob.test.BaseTestCase;
/** /**
* This test was lifted from a forum posting and shows how you can't listen to * This test was lifted from a forum posting and shows how you can't listen to
* Excel events (added post 1.9.1 Eclipse Settings.) * Excel events (added post 1.9.1 Eclipse Settings.) That test was modified make
* That test was modified make this a MSWord event listener to demonstrate * this a MSWord event listener to demonstrate that the InvocationProxy code
* that the InvocationProxy code works with MS Word Events * works with MS Word Events This also uses the 1.10 InvocationProxy to receive
* This also uses the 1.10 * the events.
* InvocationProxy to receive the events.
* <p> * <p>
* May need to run with some command line options (including from inside Eclipse). * May need to run with some command line options (including from inside
* Look in the docs area at the Jacob usage document for command line options. * Eclipse). Look in the docs area at the Jacob usage document for command line
* options.
*/ */
public class WordEventTest extends BaseTestCase { public class WordEventTest extends BaseTestCase {
/** /**
* load up word, register for events and make stuff happen * load up word, register for events and make stuff happen
*
* @param args * @param args
*/ */
public void testCaptureWordEvents() { public void testCaptureWordEvents() {
@@ -50,7 +51,8 @@ public class WordEventTest extends BaseTestCase {
// the jacob active X api instead of the Dispatch api // the jacob active X api instead of the Dispatch api
System.out.println("version=" + axc.getPropertyAsString("Version")); System.out.println("version=" + axc.getPropertyAsString("Version"));
axc.setProperty("Visible", true); axc.setProperty("Visible", true);
ActiveXComponent documents = axc.getPropertyAsComponent("Documents"); ActiveXComponent documents = axc
.getPropertyAsComponent("Documents");
if (documents == null) { if (documents == null) {
fail("unable to get documents"); fail("unable to get documents");
} }
@@ -61,12 +63,15 @@ public class WordEventTest extends BaseTestCase {
fail("Failed to attach to " + pid + ": " + cfe.getMessage()); fail("Failed to attach to " + pid + ": " + cfe.getMessage());
} }
System.out.println( System.out
"Someone needs to add some MSWord commands to this to " + .println("Someone needs to add some MSWord commands to this to "
"make some on screen stuff happens so the tester " + + "make some on screen stuff happens so the tester "
"thinks we tested something"); + "thinks we tested something");
} }
/**
* a class that receives messages from word
*/
public class WordEvents extends InvocationProxy { public class WordEvents extends InvocationProxy {
/** /**
* Constructor so we can create an instance that implements invoke() * Constructor so we can create an instance that implements invoke()
@@ -75,10 +80,12 @@ public class WordEvents extends InvocationProxy {
} }
/** /**
* override the invoke() method to log all the events without writing a bunch of code * override the invoke() method to log all the events without writing a
* bunch of code
*/ */
public Variant invoke(String methodName, Variant targetParameter[]) { public Variant invoke(String methodName, Variant targetParameter[]) {
System.out.println("Received event from Windows program" + methodName); System.out.println("Received event from Windows program"
+ methodName);
return null; return null;
} }

View File

@@ -0,0 +1,236 @@
package com.jacob.test.excel;
import java.io.File;
import java.util.LinkedList;
import java.util.List;
import java.util.StringTokenizer;
import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComThread;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
import com.jacob.test.BaseTestCase;
/**
* this test verifies that you can call toString() on a Variant extracted from
* Excel that contains a 2 dimensional array of doubles. 1.14M5 and earlier blew
* up on this because two objects pointed at the same windows memory space SF 1840487
*/
public class ControllerTest extends BaseTestCase {
private Controller controller;
protected void setUp() {
controller = new Controller();
}
public void testGetColumnA() {
List<String> list = controller.getColumnA(super
.getWindowsFilePathToPackageResource("teste.xls", this
.getClass()));
assertEquals(50, list.size());
}
public void testGetColumnB() {
List<String> list = controller.getColumnB(super
.getWindowsFilePathToPackageResource("teste.xls", this
.getClass()));
assertEquals(40, list.size());
}
/**
* This class looks bad because it is a compressed version that was
* originally in 3 different files as part of a bug submission. I didn't
* want to simplify it because it might no longer demonstrate the problem we
* were trying to fix
*/
public class Controller {
private List<String> columnA;
private List<String> columnB;
public List<String> getColumnA(String pathToTest) {
load(pathToTest);
return columnA;
}
public List<String> getColumnB(String pathToTest) {
load(pathToTest);
return columnB;
}
public void load(String pathToTest) {
if (columnA == null || columnB == null) {
File excelFile = new File(pathToTest);
executaExcelCallBack(excelFile.getAbsolutePath(), "password");
}
}
public void executaExcelCallBack(String path, String password) {
// ComThread.InitSTA();
ComThread.InitMTA();
ActiveXComponent excel = new ActiveXComponent("Excel.Application");
try {
excel.setProperty("Visible", false);
Dispatch workbooks = excel.getProperty("Workbooks")
.toDispatch();
Dispatch workbook = Dispatch.call(workbooks, "Open", path, // FileName
3, // UpdateLinks
false, // Readonly
5, // Format
password // Password
).toDispatch();
Dispatch sheets = Dispatch.call(workbook, "Worksheets")
.toDispatch();
System.out.println("Before executa");
executa(excel, sheets);
System.out.println("After executa");
Dispatch.call(workbook, "Close", new Variant(false));
Dispatch.call(workbooks, "Close");
System.out.println("After Close");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Before Quit");
excel.invoke("Quit", new Variant[] {});
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("After Quit, Before Release()");
ComThread.Release();
System.out.println("After Release()");
}
}
/**
* Constante para configurar a planilha em modo "Calculation" autom<6F>tico
*/
public static final int CALC_AUTOMATICO = -4105;
/**
* Constante para configurar a planilha em modo "Calculation" manual
*/
public static final int CALC_MANUAL = -4135;
/**
* Escreve um determinado valor em uma c<>lula da pasta em quest<73>o. O
* valor <20> escrito configurando a propriedade Value da c<>lula
*
* @param celula -
* c<>lula para escrever novo valor
* @param sheet -
* pasta da planilha em quest<73>o
* @param valor -
* valor a ser escrito na celula
*/
public void informarValorCelula(String celula, Dispatch sheet,
String valor) {
System.out.println("Entered informarValorCelula");
Dispatch cel = obterCelula(celula, sheet);
Dispatch.put(cel, "Value", valor);
System.out.println("Exiting informarValorCelula");
}
/**
* Obtem o valor de contido em uma c<>lula. O valor representa o conte<74>do
* da propriedade Value da c<>lula
*
* @param celula -
* c<>lula a ser lida
* @param sheet -
* pasta da planilha que cont<6E>m a c<>lula
* @return - conte<74>do da propriedade Value
*/
public Variant obterValorCelula(String celula, Dispatch sheet) {
System.out.println("Entered obterValorCelula");
Dispatch d = obterCelula(celula, sheet);
Variant returnedValue = Dispatch.get(d, "Value");
System.out.println("Exiting obterValorCelula");
return returnedValue;
}
/**
* Obtem refer<65>ncia para a c<>lua ou conjunto de c<>lulas especificado no
* parametro
*
* @param celula -
* Refer<65>ncia para c<>lula ou conjunto de c<>lulas. A String
* "A1" referencia a coluna A e linha 1. A Sting "A1:A10"
* referencia as c<>lulas compreendidas no intervalo entre a
* c<>lua A1 e a c<>lula A10
* @param sheet -
* pasta da planilha qye cont<6E>m as c<>lulas
* @return - referencia para um c<>lula ou conjunto de c<>lulas,
* dependendo do par<61>metro passado
*/
public Dispatch obterCelula(String celula, Dispatch sheet) {
System.out.println("Entered obterCelula");
Dispatch d = Dispatch.invoke(sheet, "Range", Dispatch.Get,
new Object[] { celula }, new int[1]).toDispatch();
System.out.println("Exiting obterCelula");
return d;
}
/**
* Obtem os valores de um conjunto de c<>lulas
*
* @param celulas -
* Refer<65>ncia para conjunto de c<>lulas
* @param sheet -
* Pasta que cont<6E>m as c<>lulas referenciadas
* @return - Lista onde cada elemento <20> o valor de uma c<>lula
* referenciada na conjunto
*/
public List<String> obterValoresRange(String celulas, Dispatch sheet) {
List<String> valores = new LinkedList<String>();
// obtem valor das celulas como um Variant
Variant var = obterValorCelula(celulas, sheet);
// toString da Variant <20> interpretado por um StringTokenizer e os
// tokens
// inseridos na lista de retorno
String arrayAsString = null;
System.out
.println("Calling toString() on the Variant that is an array will blow up "
+ var.getvt() + " --> " + arrayAsString);
arrayAsString = var.toString();
StringTokenizer st = new StringTokenizer(arrayAsString, "\n");
while (st.hasMoreTokens()) {
valores.add(st.nextToken().trim());
}
return valores;
}
/**
* M<>todo para execu<63><75>o de a<><61>o a ser executada em planilha excel.
*
* @param xl -
* Referencia para aplica<63><61>o excel
* @param sheets -
* Referencia para conjunto de pastas da planilha
*/
public void executa(ActiveXComponent xl, Dispatch sheets) {
System.out.println("Entered private ExcellCallBack executa()");
Dispatch sheet = Dispatch.call(sheets, "Item", "Plan1")
.toDispatch();
columnA = obterValoresRange("A1:A50", sheet);
columnB = obterValoresRange("B1:B40", sheet);
System.out.println("Exiting private ExcellCallBack executa()");
}
}
}

Binary file not shown.

View File

@@ -17,28 +17,30 @@ import com.jacob.test.BaseTestCase;
/** /**
* *
* power point test program posted to sourceforge to demonstrate memory problem. * power point test program posted to sourceforge to demonstrate memory problem.
* The submitter stated they had the problem on windows 2000 with office 2000 * The submitter stated they had the problem on windows 2000 with office 2000 I
* I have been unable to duplicate on windows XP with office 2003. * have been unable to duplicate on windows XP with office 2003. I am comitting
* I am comitting this to the tree just in case we need to come back to it. * this to the tree just in case we need to come back to it.
* <P> * <P>
* This relies on BaseTestCase to provide the root path to the file under test * This relies on BaseTestCase to provide the root path to the file under test
* <p> * <p>
* May need to run with some command line options (including from inside Eclipse). * May need to run with some command line options (including from inside
* Look in the docs area at the Jacob usage document for command line options. * Eclipse). Look in the docs area at the Jacob usage document for command line
* options.
*/ */
public class PowerpointTest extends BaseTestCase { public class PowerpointTest extends BaseTestCase {
private static final int NUM_THREADS = 5; private static final int NUM_THREADS = 5;
protected static final int NUM_ITERATIONS = 50; protected static final int NUM_ITERATIONS = 50;
/** /**
* main program that lets us run this as a test * main program that lets us run this as a test
*
* @param args * @param args
*/ */
public void testPowerpoint() { public void testPowerpoint() {
ComThread.InitMTA(); ComThread.InitMTA();
ActiveXComponent component = new ActiveXComponent("Powerpoint.Application"); ActiveXComponent component = new ActiveXComponent(
"Powerpoint.Application");
Dispatch comPowerpoint = component.getObject(); Dispatch comPowerpoint = component.getObject();
try { try {
@@ -69,8 +71,8 @@ public class PowerpointTest extends BaseTestCase {
Dispatch.call(comPowerpoint, "Quit"); Dispatch.call(comPowerpoint, "Quit");
for (int i = 0; i < NUM_THREADS; i++) { for (int i = 0; i < NUM_THREADS; i++) {
if (threads[i].threadFailedWithException != null) { if (threads[i].threadFailedWithException != null) {
fail ("caught unexpected exception in thread "+ fail("caught unexpected exception in thread "
threads[i].threadFailedWithException); + threads[i].threadFailedWithException);
} }
} }
} finally { } finally {
@@ -79,6 +81,9 @@ public class PowerpointTest extends BaseTestCase {
} }
/**
* the thread class that runs power point
*/
public class PowerpointTestThread extends Thread { public class PowerpointTestThread extends Thread {
/** /**
* holds any caught exception so the main/test case can see them * holds any caught exception so the main/test case can see them
@@ -88,6 +93,12 @@ public class PowerpointTestThread extends Thread {
private int threadID; private int threadID;
private Dispatch comPowerpoint; private Dispatch comPowerpoint;
/**
* thread constructor
*
* @param threadID
* @param comPowerpoint
*/
public PowerpointTestThread(int threadID, Dispatch comPowerpoint) { public PowerpointTestThread(int threadID, Dispatch comPowerpoint) {
super("TestThread " + threadID); super("TestThread " + threadID);
this.threadID = threadID; this.threadID = threadID;
@@ -95,36 +106,44 @@ public class PowerpointTestThread extends Thread {
} }
public void run() { public void run() {
System.out.println("Thread \""+Thread.currentThread().getName()+"\" started"); System.out.println("Thread \"" + Thread.currentThread().getName()
+ "\" started");
System.out.flush(); System.out.flush();
ComThread.InitMTA(); ComThread.InitMTA();
try { try {
for (int i = 0; i < NUM_ITERATIONS; i++) { for (int i = 0; i < NUM_ITERATIONS; i++) {
if (i % 10 == 0) { if (i % 10 == 0) {
System.out.println(Thread.currentThread().getName()+": Iteration "+i); System.out.println(Thread.currentThread().getName()
+ ": Iteration " + i);
System.out.flush(); System.out.flush();
} }
Dispatch comPresentations = Dispatch.get(comPowerpoint,"Presentations").toDispatch(); Dispatch comPresentations = Dispatch.get(comPowerpoint,
Dispatch comPresentation = Dispatch.call(comPresentations, "Presentations").toDispatch();
Dispatch comPresentation = Dispatch.call(
comPresentations,
"Open", "Open",
getWindowsFilePathToPackageResource("test"+threadID+".ppt",this.getClass()), getWindowsFilePathToPackageResource("test"
new Integer(0), + threadID + ".ppt", this.getClass()),
new Integer(0), new Integer(0), new Integer(0), new Integer(0))
new Integer(0)).toDispatch(); .toDispatch();
Dispatch.call(comPresentation, "Close"); Dispatch.call(comPresentation, "Close");
} }
} catch (ComFailException cfe) { } catch (ComFailException cfe) {
threadFailedWithException = cfe; threadFailedWithException = cfe;
System.err.println(Thread.currentThread().getName()+"\" while working on: "+ System.err.println(Thread.currentThread().getName()
getWindowsFilePathToPackageResource("test"+threadID+".ppt",this.getClass())); + "\" while working on: "
+ getWindowsFilePathToPackageResource("test" + threadID
+ ".ppt", this.getClass()));
cfe.printStackTrace(); cfe.printStackTrace();
} catch (Exception e) { } catch (Exception e) {
threadFailedWithException = e; threadFailedWithException = e;
System.err.println("Error in Thread \""+Thread.currentThread().getName()+"\":"); System.err.println("Error in Thread \""
+ Thread.currentThread().getName() + "\":");
e.printStackTrace(); e.printStackTrace();
} finally { } finally {
ComThread.Release(); ComThread.Release();
System.out.println("Thread \""+Thread.currentThread().getName()+"\" finished"); System.out.println("Thread \""
+ Thread.currentThread().getName() + "\" finished");
System.out.flush(); System.out.flush();
} }
} }

View File

@@ -7,66 +7,194 @@ import com.jacob.test.BaseTestCase;
/** /**
* SafeArrayTest Program * SafeArrayTest Program
* *
* This is more of an exerciser. It doesn't verify that it gets back * This is more of an exerciser. It doesn't verify that it gets back what it
* what it expects like a junit test would * expects like a junit test would
* <p> * <p>
* May need to run with some command line options (including from inside Eclipse). * May need to run with some command line options (including from inside
* Look in the docs area at the Jacob usage document for command line options. * Eclipse). Look in the docs area at the Jacob usage document for command line
* options.
* *
*/ */
public class SafeArrayBasicTest extends BaseTestCase { public class SafeArrayBasicTest extends BaseTestCase {
public void testBasicSafeArray(){
//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++) { public void testShortSafeArray() {
System.out.println("toInt=" + ai[i]); short sourceData[] = new short[] { 1, 2, 3 };
SafeArray saUnderTest = new SafeArray(Variant.VariantVariant, 3);
saUnderTest.fromShortArray(sourceData);
short[] extractedFromSafeArray = saUnderTest.toShortArray();
for (int i = 0; i < extractedFromSafeArray.length; i++) {
assertEquals("" + i, sourceData[i], extractedFromSafeArray[i]);
} }
double[] ad = sa.toDoubleArray();
for (int i = 0; i < ad.length; i++) { assertEquals("single get failed: ", sourceData[2], saUnderTest
System.out.println("toDouble=" + ad[i]); .getShort(2));
// test conversion
int[] extractedFromSafeArrayInt = saUnderTest.toIntArray();
for (int i = 0; i < extractedFromSafeArray.length; i++) {
assertEquals("" + i, sourceData[i], extractedFromSafeArrayInt[i]);
} }
sa.fromIntArray(new int[] { 100000, 200000, 300000 }); // test conversion
System.out.println("sa int=" + sa); double[] extractedFromSafeArrayDouble = saUnderTest.toDoubleArray();
ai = sa.toIntArray(); for (int i = 0; i < extractedFromSafeArrayDouble.length; i++) {
for (int i = 0; i < ai.length; i++) { assertEquals("" + i, new Double(sourceData[i]).doubleValue(),
System.out.println("toInt=" + ai[i]); extractedFromSafeArrayDouble[i]);
} }
ad = sa.toDoubleArray(); // test conversion
for (int i = 0; i < ad.length; i++) { Variant extractedFromSafeArrayVariant[] = saUnderTest.toVariantArray();
System.out.println("toDouble=" + ad[i]); for (int i = 0; i < extractedFromSafeArrayVariant.length; i++) {
assertEquals("" + i, sourceData[i],
extractedFromSafeArrayVariant[i].getShort());
} }
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 }); public void testIntSafeArray() {
System.out.println("sa bool=" + sa); int sourceData[] = new int[] { 100000, 200000, 300000 };
av = sa.toVariantArray(); SafeArray saUnderTest = new SafeArray(Variant.VariantVariant, 3);
for (int i = 0; i < av.length; i++) { saUnderTest.fromIntArray(sourceData);
System.out.println("toVariant=" + av[i]); int[] extractedFromSafeArray = saUnderTest.toIntArray();
for (int i = 0; i < extractedFromSafeArray.length; i++) {
assertEquals("" + i, sourceData[i], extractedFromSafeArray[i]);
} }
sa.fromCharArray(new char[] { 'a', 'b', 'c', 'd' }); assertEquals("single get failed: ", sourceData[2], saUnderTest
System.out.println("sa char=" + sa); .getInt(2));
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);
} }
/**
*
*/
public void testLongSafeArray() {
long sourceData[] = new long[] { 2L << 40, 3L << 41, 4L << 42 };
SafeArray saUnderTest = new SafeArray(Variant.VariantVariant, 3);
saUnderTest.fromLongArray(sourceData);
long[] extractedFromSafeArray = saUnderTest.toLongArray();
for (int i = 0; i < extractedFromSafeArray.length; i++) {
assertEquals("" + i, sourceData[i], extractedFromSafeArray[i]);
}
assertEquals("single get failed: ", sourceData[2], saUnderTest
.getLong(2));
}
/**
*
*/
public void testDoubleSafeArray() {
double sourceData[] = new double[] { 1.5, 2.5, 3.5 };
SafeArray saUnderTest = new SafeArray(Variant.VariantVariant, 3);
saUnderTest.fromDoubleArray(sourceData);
double[] extractedFromSafeArray = saUnderTest.toDoubleArray();
for (int i = 0; i < extractedFromSafeArray.length; i++) {
assertEquals("" + i, sourceData[i], extractedFromSafeArray[i]);
}
assertEquals("single get failed: ", sourceData[2], saUnderTest
.getDouble(2));
}
/**
*
*/
public void testFloatSafeArray() {
float sourceData[] = new float[] { 1.5F, 2.5F, 3.5F };
SafeArray saUnderTest = new SafeArray(Variant.VariantVariant, 3);
saUnderTest.fromFloatArray(sourceData);
float[] extractedFromSafeArray = saUnderTest.toFloatArray();
for (int i = 0; i < extractedFromSafeArray.length; i++) {
assertEquals("" + i, sourceData[i], extractedFromSafeArray[i]);
}
}
/**
*
*/
public void testBooleanSafeArray() {
boolean sourceData[] = new boolean[] { true, false, true, false };
SafeArray saUnderTest = new SafeArray(Variant.VariantVariant, 3);
saUnderTest.fromBooleanArray(sourceData);
boolean[] extractedFromSafeArray = saUnderTest.toBooleanArray();
for (int i = 0; i < extractedFromSafeArray.length; i++) {
assertEquals("" + i, sourceData[i], extractedFromSafeArray[i]);
}
assertEquals("single get failed: ", sourceData[2], saUnderTest
.getBoolean(2));
// test conversion
Variant extractedFromSafeArrayVariant[] = saUnderTest.toVariantArray();
for (int i = 0; i < extractedFromSafeArrayVariant.length; i++) {
assertEquals("" + i, sourceData[i],
extractedFromSafeArrayVariant[i].getBoolean());
}
}
/**
*
*/
public void testCharSafeArray() {
char sourceData[] = new char[] { 'a', 'b', 'c', 'd' };
SafeArray saUnderTest = new SafeArray(Variant.VariantVariant, 3);
saUnderTest.fromCharArray(sourceData);
char[] extractedFromSafeArray = saUnderTest.toCharArray();
for (int i = 0; i < extractedFromSafeArray.length; i++) {
assertEquals("" + i, sourceData[i], extractedFromSafeArray[i]);
}
assertEquals("single get failed: ", sourceData[2], saUnderTest
.getChar(2));
}
/**
*
*/
public void testStringSaveArray() {
String sourceData[] = new String[] { "hello", "from", "java", "com" };
SafeArray saUnderTest = new SafeArray(Variant.VariantVariant, 3);
saUnderTest.fromStringArray(sourceData);
String[] extractedFromSafeArray = saUnderTest.toStringArray();
for (int i = 0; i < extractedFromSafeArray.length; i++) {
assertEquals("" + i, sourceData[i], extractedFromSafeArray[i]);
}
assertEquals("single get failed: ", sourceData[2], saUnderTest
.getString(2));
// test conversion
Variant extractedFromSafeArrayVariant[] = saUnderTest.toVariantArray();
for (int i = 0; i < extractedFromSafeArrayVariant.length; i++) {
assertEquals("" + i, sourceData[i],
extractedFromSafeArrayVariant[i].getString());
}
}
/**
*
*/
public void testVariantSafeArray() {
Variant sourceData[] = new Variant[] { new Variant(1),
new Variant(2.3), new Variant("hi") };
SafeArray saUnderTest = new SafeArray(Variant.VariantVariant, 3);
saUnderTest.fromVariantArray(sourceData);
Variant[] extractedFromSafeArray = saUnderTest.toVariantArray();
for (int i = 0; i < extractedFromSafeArray.length; i++) {
assertEquals("" + i, sourceData[i].toString(),
extractedFromSafeArray[i].toString());
}
assertEquals("single get failed: ", sourceData[2].toString(),
saUnderTest.getVariant(2).toString());
}
/**
* test method that verifies setting of bounds in multi-dimensional arrays
*/
public void testSafeArrayNumDimensions() { public void testSafeArrayNumDimensions() {
int[] lowerBounds = new int[] { 0, 0, 0 }; int[] lowerBounds = new int[] { 0, 0, 0 };
int[] dimensionSizes = new int[] { 3, 3, 3 }; int[] dimensionSizes = new int[] { 3, 3, 3 };
@@ -75,13 +203,29 @@ public class SafeArrayBasicTest extends BaseTestCase {
dimensionSizes); dimensionSizes);
System.out.println("Num Dimensions = " + sa3x3.getNumDim()); System.out.println("Num Dimensions = " + sa3x3.getNumDim());
for (int i = 1; i <= sa3x3.getNumDim(); i++) { for (int safeArrayDimension = 1; safeArrayDimension <= sa3x3
System.out.println("Dimension number = " + i); .getNumDim(); safeArrayDimension++) {
System.out.println("Lower bound = " + sa3x3.getLBound(i)); int configArrayIndex = safeArrayDimension - 1;
System.out.println("Upper bound = " + sa3x3.getUBound(i)); assertEquals("unexpected lower bound value ",
lowerBounds[configArrayIndex], sa3x3
.getLBound(safeArrayDimension));
assertEquals("unexpeced upper bound value ",
(dimensionSizes[configArrayIndex] - 1)
+ lowerBounds[configArrayIndex], sa3x3
.getUBound(safeArrayDimension));
}
} }
int fill = 0; /**
* test the set and get method on multi-dimensional arrays
*/
public void testSafeArrayMultiDimension() {
int[] lowerBounds = new int[] { 0, 0, 0 };
int[] dimensionSizes = new int[] { 3, 3, 3 };
SafeArray sa3x3 = new SafeArray(Variant.VariantVariant, lowerBounds,
dimensionSizes);
int[] indices = new int[] { 0, 0, 0 }; int[] indices = new int[] { 0, 0, 0 };
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
@@ -90,10 +234,17 @@ public class SafeArrayBasicTest extends BaseTestCase {
indices[1] = j; indices[1] = j;
for (int k = 0; k < 3; k++) { for (int k = 0; k < 3; k++) {
indices[2] = k; indices[2] = k;
int fill = 0;
fill = i * 100 + j * 10 + k; fill = i * 100 + j * 10 + k;
sa3x3.setInt(indices, fill); sa3x3.setInt(indices, fill);
System.out.println("sa[" + i + "][" + j + "][" + k + "] = " assertEquals(fill, sa3x3.getInt(indices));
+ sa3x3.getInt(indices));
long fillLong = 0L;
// Pick a number bigger than 2^31
fillLong = 100000000000000L * fill;
sa3x3.setLong(indices, fillLong);
assertEquals(fillLong, sa3x3.getLong(indices));
} }
} }
} }

View File

@@ -7,6 +7,9 @@ import com.jacob.com.SafeArray;
import com.jacob.com.Variant; import com.jacob.com.Variant;
import com.jacob.test.BaseTestCase; import com.jacob.test.BaseTestCase;
/**
* Test class to verify dispatch with SafeArray
*/
public class SafeArrayDispatchTest extends BaseTestCase { public class SafeArrayDispatchTest extends BaseTestCase {
public void testDispatchWithSafeArray() { public void testDispatchWithSafeArray() {
try { try {

View File

@@ -3,20 +3,21 @@ package com.jacob.test.safearray;
import com.jacob.activeX.ActiveXComponent; import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComThread; import com.jacob.com.ComThread;
import com.jacob.com.Dispatch; import com.jacob.com.Dispatch;
import com.jacob.com.JacobObject; import com.jacob.com.JacobReleaseInfo;
import com.jacob.com.SafeArray; import com.jacob.com.SafeArray;
import com.jacob.com.Variant; import com.jacob.com.Variant;
import com.jacob.test.BaseTestCase; import com.jacob.test.BaseTestCase;
/** /**
* This test program demonstrates a weak in the setString(int[],String) method in SafeArray. * This test program demonstrates a weak in the setString(int[],String) method
* To see the leak: * in SafeArray. To see the leak:
* <ul> * <ul>
* <li>Bring up the windows task manager and click on the performance tab. * <li>Bring up the windows task manager and click on the performance tab.
* <li>Run the test program * <li>Run the test program
* </ul> * </ul>
* You should see the Page File Usage History graph rise at te end of every cycle. * You should see the Page File Usage History graph rise at te end of every
* Running the same program with setString(r,c,String) does not show the same symptoms * cycle. Running the same program with setString(r,c,String) does not show the
* same symptoms
*/ */
public class SafeArrayLeak extends BaseTestCase { public class SafeArrayLeak extends BaseTestCase {
@@ -36,7 +37,7 @@ public class SafeArrayLeak extends BaseTestCase {
SafeArray sa = null; SafeArray sa = null;
// -Dcom.jacob.autogc=true // -Dcom.jacob.autogc=true
System.out.println("Jacob version: "+JacobObject.getBuildVersion()); System.out.println("Jacob version: " + JacobReleaseInfo.getBuildVersion());
for (int t = 0; t < 10; t++) { for (int t = 0; t < 10; t++) {
// look at a large range of cells // look at a large range of cells
@@ -44,7 +45,8 @@ public class SafeArrayLeak extends BaseTestCase {
try { try {
xl = new ActiveXComponent("Excel.Application"); xl = new ActiveXComponent("Excel.Application");
System.out.println("Excel version=" + xl.getProperty("Version")); System.out
.println("Excel version=" + xl.getProperty("Version"));
xl.setProperty("Visible", new Variant(false)); xl.setProperty("Visible", new Variant(false));
workbooks = xl.getProperty("Workbooks").toDispatch(); workbooks = xl.getProperty("Workbooks").toDispatch();
@@ -56,8 +58,7 @@ public class SafeArrayLeak extends BaseTestCase {
sheet = Dispatch.get(workbook, "ActiveSheet").toDispatch(); sheet = Dispatch.get(workbook, "ActiveSheet").toDispatch();
// grab the whole range specified above. // grab the whole range specified above.
tabCells = Dispatch.invoke(sheet, "Range", Dispatch.Get, tabCells = Dispatch.invoke(sheet, "Range", Dispatch.Get,
new Object[] { position }, new Object[] { position }, new int[1]).toDispatch();
new int[1]).toDispatch();
sa = Dispatch.get(tabCells, "Value").toSafeArray(true); sa = Dispatch.get(tabCells, "Value").toSafeArray(true);
@@ -89,20 +90,16 @@ public class SafeArrayLeak extends BaseTestCase {
Variant f = new Variant(false); Variant f = new Variant(false);
Dispatch.call(workbook, "Close", f); Dispatch.call(workbook, "Close", f);
System.out.println("Close"); System.out.println("Close");
} } catch (Exception e) {
catch(Exception e) {
e.printStackTrace(); e.printStackTrace();
} } finally {
finally {
if (sa != null) { if (sa != null) {
try { try {
sa.safeRelease(); sa.safeRelease();
} } catch (Exception e) {
catch(Exception e) {
e.printStackTrace(); e.printStackTrace();
} } finally {
finally {
sa = null; sa = null;
} }
} }
@@ -110,11 +107,9 @@ public class SafeArrayLeak extends BaseTestCase {
if (tabCells != null) { if (tabCells != null) {
try { try {
tabCells.safeRelease(); tabCells.safeRelease();
} } catch (Exception e) {
catch(Exception e) {
e.printStackTrace(); e.printStackTrace();
} } finally {
finally {
tabCells = null; tabCells = null;
} }
} }
@@ -122,11 +117,9 @@ public class SafeArrayLeak extends BaseTestCase {
if (sheet != null) { if (sheet != null) {
try { try {
sheet.safeRelease(); sheet.safeRelease();
} } catch (Exception e) {
catch(Exception e) {
e.printStackTrace(); e.printStackTrace();
} } finally {
finally {
sheet = null; sheet = null;
} }
} }
@@ -134,11 +127,9 @@ public class SafeArrayLeak extends BaseTestCase {
if (workSheets != null) { if (workSheets != null) {
try { try {
workSheets.safeRelease(); workSheets.safeRelease();
} } catch (Exception e) {
catch(Exception e) {
e.printStackTrace(); e.printStackTrace();
} } finally {
finally {
workSheets = null; workSheets = null;
} }
} }
@@ -146,11 +137,9 @@ public class SafeArrayLeak extends BaseTestCase {
if (workbook != null) { if (workbook != null) {
try { try {
workbook.safeRelease(); workbook.safeRelease();
} } catch (Exception e) {
catch(Exception e) {
e.printStackTrace(); e.printStackTrace();
} } finally {
finally {
workbook = null; workbook = null;
} }
} }
@@ -158,11 +147,9 @@ public class SafeArrayLeak extends BaseTestCase {
if (workbooks != null) { if (workbooks != null) {
try { try {
workbooks.safeRelease(); workbooks.safeRelease();
} } catch (Exception e) {
catch(Exception e) {
e.printStackTrace(); e.printStackTrace();
} } finally {
finally {
workbooks = null; workbooks = null;
} }
} }
@@ -170,18 +157,15 @@ public class SafeArrayLeak extends BaseTestCase {
if (xl != null) { if (xl != null) {
try { try {
xl.invoke("Quit", new Variant[] {}); xl.invoke("Quit", new Variant[] {});
} } catch (Exception e) {
catch(Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
try { try {
xl.safeRelease(); xl.safeRelease();
} } catch (Exception e) {
catch(Exception e) {
e.printStackTrace(); e.printStackTrace();
} } finally {
finally {
xl = null; xl = null;
} }
} }

View File

@@ -7,92 +7,65 @@ import com.jacob.test.BaseTestCase;
/** /**
* <p> * <p>
* May need to run with some command line options (including from inside Eclipse). * May need to run with some command line options (including from inside
* Look in the docs area at the Jacob usage document for command line options. * Eclipse). Look in the docs area at the Jacob usage document for command line
* options.
* <p> * <p>
* SF 1085370 * SF 1085370 In my understatnding, an instance of SafeArray java class has a
In my understatnding, an instance of SafeArray java * value of a pointer to VARIANT structure that contains a pointer to a
class has a * SAFEARRAY strucuture.
value of a pointer to VARIANT structure that contains a *
pointer to * On the other hand, we can create a Variant object from the SafeArray object
a SAFEARRAY strucuture. * like this: SafeArray sa = ...; Variant val = new Variant(sa); the val object
* has a pointer to another VARIANT structure that contains a pointer to the
On the other hand, we can create a Variant object from * same SAFEARRAY structure.
the *
SafeArray object like this: * In this case, the val object has a pointer to another VARIANT that contains a
SafeArray sa = ...; * pointer to the same SAFEARRAY like this:
Variant val = new Variant(sa); *
the val object has a pointer to another VARIANT * +-----------+ |SafeArray | +------------+ | m_pV--->VARIANT(a) |
structure that * +-----------+ | VT_ARRAY| +---------+ | parray---->SAFEARRAY| +------------+
contains a pointer to the same SAFEARRAY structure. * +^--------+ | +-----------+ | |Variant | +------------+ | |
* m_pVariant--->VARIANT(b) | | +-----------+ | VT_ARRAY| | | parray-----+
In this case, the val object has a pointer to another * +------------+
VARIANT that *
contains a pointer to the same SAFEARRAY like this: * When previous objects are rereased by ComThread.Release(), first the
* VARIANT(a) is released by VariantClear() function, and second the VARIANT(b)
+-----------+ * is released by VariantClear() function too. But the SAFEARRAY was already
|SafeArray | +------------+ * released by the VARIANT(a).
| m_pV--->VARIANT(a) | *
+-----------+ | VT_ARRAY| +---------+ * So, in my enviroment (WinXP + J2SDK 1.4.1) the following java program is
| parray---->SAFEARRAY| * sometimes crash with EXCEPTION_ACCESS_VIOLATION.
+------------+ +^--------+ *
| *
+-----------+ | * To solve this problem, it is nessesary to copy the SAFEARRAY like this:
|Variant | +------------+ | *
| m_pVariant--->VARIANT(b) | | * +-----------+ |Variant | +------------+ | m_pVariant--->VARIANT(a) |
+-----------+ | VT_ARRAY| | * +-----------+ | VT_ARRAY| +---------+ | parray---->SAFEARRAY| +------------+
| parray-----+ * +|--------+ | +-----------+ | copySA() |SafeArray | +------------+ | |
+------------+ * m_pV--->VARIANT(b) | V +-----------+ | VT_ARRAY| +---------+ |
* parray---->SAFEARRAY| +------------+ +---------+
When previous objects are rereased by
ComThread.Release(),
first the VARIANT(a) is released by VariantClear()
function,
and second the VARIANT(b) is released by VariantClear()
function too.
But the SAFEARRAY was already released by the
VARIANT(a).
So, in my enviroment (WinXP + J2SDK 1.4.1) the
following java program
is sometimes crash with EXCEPTION_ACCESS_VIOLATION.
To solve this problem, it is nessesary to copy the
SAFEARRAY like this:
+-----------+
|Variant | +------------+
| m_pVariant--->VARIANT(a) |
+-----------+ | VT_ARRAY| +---------+
| parray---->SAFEARRAY|
+------------+ +|--------+
|
+-----------+ | copySA()
|SafeArray | +------------+ |
| m_pV--->VARIANT(b) | V
+-----------+ | VT_ARRAY| +---------+
| parray---->SAFEARRAY|
+------------+ +---------+
* *
* <p> * <p>
* May need to run with some command line options (including from inside Eclipse). * May need to run with some command line options (including from inside
* Look in the docs area at the Jacob usage document for command line options. * Eclipse). Look in the docs area at the Jacob usage document for command line
* options.
*/ */
public class SafeArrayReleaseTest extends BaseTestCase { public class SafeArrayReleaseTest extends BaseTestCase {
final static int MAX = 300; final static int MAX = 300;
/**
* verifies the release works on SafeArray
*/
public void testSaveArrayRelease() { public void testSaveArrayRelease() {
int count; int count;
System.out.println("Starting test for max = " + MAX); System.out.println("Starting test for max = " + MAX);
for(count = 1; count<MAX; count++) for (count = 1; count < MAX; count++) {
{
int i = 0; int i = 0;
try try {
{
ComThread.InitMTA(); ComThread.InitMTA();
for (i = 0; i < count; i++) for (i = 0; i < count; i++) {
{
SafeArray a1 = new SafeArray(Variant.VariantVariant, 2); SafeArray a1 = new SafeArray(Variant.VariantVariant, 2);
a1.setVariant(0, new Variant("foo")); a1.setVariant(0, new Variant("foo"));
a1.setVariant(1, new Variant("bar")); a1.setVariant(1, new Variant("bar"));
@@ -105,13 +78,12 @@ public class SafeArrayReleaseTest extends BaseTestCase {
ComThread.Release(); ComThread.Release();
System.gc(); System.gc();
// System.out.print("."); // System.out.print(".");
} } catch (Exception e) {
catch (Exception e)
{
fail("Test fails with i = " + i + " (max = " + MAX + ")"); fail("Test fails with i = " + i + " (max = " + MAX + ")");
} }
} }
System.gc(); System.gc();
System.out.println("\nTest ends with count = " + count + " (max = "+MAX+")"); System.out.println("\nTest ends with count = " + count + " (max = "
+ MAX + ")");
} }
} }

View File

@@ -1,21 +1,26 @@
package com.jacob.test.safearray; package com.jacob.test.safearray;
import com.jacob.com.*; import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.Dispatch;
import com.jacob.com.SafeArray;
import com.jacob.com.Variant;
import com.jacob.test.BaseTestCase; import com.jacob.test.BaseTestCase;
import com.jacob.activeX.*;
/** /**
* This does simple tests with SafeArray using Excel as a source * This does simple tests with SafeArray using Excel as a source
* <p> * <p>
* May need to run with some command line options (including from inside Eclipse). * May need to run with some command line options (including from inside
* Look in the docs area at the Jacob usage document for command line options. * Eclipse). Look in the docs area at the Jacob usage document for command line
* options.
* <p> * <p>
* This relies on BaseTestCase to provide the root path to the file under test * This relies on BaseTestCase to provide the root path to the file under test
*/ */
public class SafeArrayViaExcel extends BaseTestCase { public class SafeArrayViaExcel extends BaseTestCase {
/**
* verify safe arrays work with standard applications, Excel in this case
*/
public void testSafeArrayViaExcel() { public void testSafeArrayViaExcel() {
// deprecated
// System.runFinalizersOnExit(true);
ActiveXComponent xl = new ActiveXComponent("Excel.Application"); ActiveXComponent xl = new ActiveXComponent("Excel.Application");
try { try {
@@ -26,7 +31,8 @@ public class SafeArrayViaExcel extends BaseTestCase {
Dispatch workbook = Dispatch.call( Dispatch workbook = Dispatch.call(
workbooks, workbooks,
"Open", "Open",
getWindowsFilePathToPackageResource("SafeArrayViaExcel.xls",this.getClass())) getWindowsFilePathToPackageResource(
"SafeArrayViaExcel.xls", this.getClass()))
.toDispatch(); .toDispatch();
System.out.println("Opened File - SafeArrayViaExcel.xls\n"); System.out.println("Opened File - SafeArrayViaExcel.xls\n");
Dispatch sheet = Dispatch.get(workbook, "ActiveSheet").toDispatch(); Dispatch sheet = Dispatch.get(workbook, "ActiveSheet").toDispatch();

View File

@@ -1,8 +1,12 @@
package com.jacob.test.vbscript; package com.jacob.test.vbscript;
import com.jacob.com.*; import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComException;
import com.jacob.com.ComThread;
import com.jacob.com.Dispatch;
import com.jacob.com.DispatchEvents;
import com.jacob.com.Variant;
import com.jacob.test.BaseTestCase; import com.jacob.test.BaseTestCase;
import com.jacob.activeX.*;
/** /**
* In this case the component is created and used in the same thread and it's an * In this case the component is created and used in the same thread and it's an
@@ -33,7 +37,7 @@ public class ScriptTest extends BaseTestCase {
String scriptCommand = getSampleVPScriptForEval(); String scriptCommand = getSampleVPScriptForEval();
String lang = "VBScript"; String lang = "VBScript";
ActiveXComponent sC = new ActiveXComponent("ScriptControl"); ActiveXComponent sC = new ActiveXComponent("ScriptControl");
sControl = (Dispatch) sC.getObject(); sControl = sC.getObject();
Dispatch.put(sControl, "Language", lang); Dispatch.put(sControl, "Language", lang);
ScriptTestErrEvents te = new ScriptTestErrEvents(); ScriptTestErrEvents te = new ScriptTestErrEvents();
de = new DispatchEvents(sControl, te); de = new DispatchEvents(sControl, te);

View File

@@ -1,8 +1,14 @@
package com.jacob.test.vbscript; package com.jacob.test.vbscript;
import com.jacob.com.*; import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComException;
import com.jacob.com.ComThread;
import com.jacob.com.Dispatch;
import com.jacob.com.DispatchEvents;
import com.jacob.com.DispatchProxy;
import com.jacob.com.STA;
import com.jacob.com.Variant;
import com.jacob.test.BaseTestCase; import com.jacob.test.BaseTestCase;
import com.jacob.activeX.*;
/** /**
* This example demonstrates how to make calls between two different STA's. * This example demonstrates how to make calls between two different STA's.
@@ -21,8 +27,9 @@ import com.jacob.activeX.*;
* multiple threads to access a Dispatch pointer, then create that many * multiple threads to access a Dispatch pointer, then create that many
* DispatchProxy objects. * DispatchProxy objects.
* <p> * <p>
* May need to run with some command line options (including from inside Eclipse). * May need to run with some command line options (including from inside
* Look in the docs area at the Jacob usage document for command line options. * Eclipse). Look in the docs area at the Jacob usage document for command line
* options.
*/ */
public class ScriptTest2 extends BaseTestCase { public class ScriptTest2 extends BaseTestCase {

View File

@@ -26,8 +26,9 @@ import com.jacob.test.BaseTestCase;
* multiple threads to access a Dispatch pointer, then create that many * multiple threads to access a Dispatch pointer, then create that many
* DispatchProxy objects. * DispatchProxy objects.
* <p> * <p>
* May need to run with some command line options (including from inside Eclipse). * May need to run with some command line options (including from inside
* Look in the docs area at the Jacob usage document for command line options. * Eclipse). Look in the docs area at the Jacob usage document for command line
* options.
*/ */
public class ScriptTest2ActiveX extends BaseTestCase { public class ScriptTest2ActiveX extends BaseTestCase {
public static ActiveXComponent sC; public static ActiveXComponent sC;

View File

@@ -1,8 +1,12 @@
package com.jacob.test.vbscript; package com.jacob.test.vbscript;
import com.jacob.com.*; import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComException;
import com.jacob.com.ComThread;
import com.jacob.com.Dispatch;
import com.jacob.com.DispatchEvents;
import com.jacob.com.Variant;
import com.jacob.test.BaseTestCase; import com.jacob.test.BaseTestCase;
import com.jacob.activeX.*;
/** /**
* Here we create the ScriptControl component in a separate MTA thread and then * Here we create the ScriptControl component in a separate MTA thread and then
@@ -10,8 +14,9 @@ import com.jacob.activeX.*;
* MTA thread. If you try to create it as an STA then you will not be able to * 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. * make calls into a component running in another thread.
* <p> * <p>
* May need to run with some command line options (including from inside Eclipse). * May need to run with some command line options (including from inside
* Look in the docs area at the Jacob usage document for command line options. * Eclipse). Look in the docs area at the Jacob usage document for command line
* options.
*/ */
public class ScriptTest3 extends BaseTestCase { public class ScriptTest3 extends BaseTestCase {
@@ -34,8 +39,10 @@ public class ScriptTest3 extends BaseTestCase {
// should we get this? // should we get this?
} }
Variant result = Dispatch.call(sControl, "Eval", getSampleVPScriptForEval()); Variant result = Dispatch.call(sControl, "Eval",
System.out.println("eval(" + getSampleVPScriptForEval() + ") = " + result); getSampleVPScriptForEval());
System.out.println("eval(" + getSampleVPScriptForEval() + ") = "
+ result);
System.out.println("setting quit"); System.out.println("setting quit");
ScriptTest3.quit = true; ScriptTest3.quit = true;
} catch (ComException e) { } catch (ComException e) {
@@ -54,13 +61,14 @@ public class ScriptTest3 extends BaseTestCase {
System.out.println("OnInit"); System.out.println("OnInit");
String lang = "VBScript"; String lang = "VBScript";
sC = new ActiveXComponent("ScriptControl"); sC = new ActiveXComponent("ScriptControl");
sControl = (Dispatch) sC.getObject(); sControl = sC.getObject();
Dispatch.put(sControl, "Language", lang); Dispatch.put(sControl, "Language", lang);
ScriptTestErrEvents te = new ScriptTestErrEvents(); ScriptTestErrEvents te = new ScriptTestErrEvents();
de = new DispatchEvents(sControl, te); de = new DispatchEvents(sControl, te);
System.out.println("sControl=" + sControl); System.out.println("sControl=" + sControl);
while (!quit) while (!quit) {
sleep(100); sleep(100);
}
ComThread.Release(); ComThread.Release();
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();

View File

@@ -1,8 +1,11 @@
package com.jacob.test.vbscript; package com.jacob.test.vbscript;
import com.jacob.com.*; import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComException;
import com.jacob.com.ComThread;
import com.jacob.com.DispatchEvents;
import com.jacob.com.Variant;
import com.jacob.test.BaseTestCase; import com.jacob.test.BaseTestCase;
import com.jacob.activeX.*;
/** /**
* Here we create the ScriptControl component in a separate MTA thread and then * Here we create the ScriptControl component in a separate MTA thread and then
@@ -33,9 +36,8 @@ public class ScriptTest3ActiveX extends BaseTestCase {
} }
Variant result = sC.invoke("Eval", getSampleVPScriptForEval()); Variant result = sC.invoke("Eval", getSampleVPScriptForEval());
System.out System.out.println("eval(" + getSampleVPScriptForEval() + ") = "
.println("eval(" + getSampleVPScriptForEval() + result);
+ ") = " + result);
System.out.println("setting quit"); System.out.println("setting quit");
ScriptTest3ActiveX.quit = true; ScriptTest3ActiveX.quit = true;
} catch (ComException e) { } catch (ComException e) {
@@ -58,8 +60,9 @@ public class ScriptTest3ActiveX extends BaseTestCase {
ScriptTestErrEvents te = new ScriptTestErrEvents(); ScriptTestErrEvents te = new ScriptTestErrEvents();
de = new DispatchEvents(sC, te); de = new DispatchEvents(sC, te);
System.out.println("sControl=" + sC); System.out.println("sControl=" + sC);
while (!quit) while (!quit) {
sleep(100); sleep(100);
}
ComThread.Release(); ComThread.Release();
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();

View File

@@ -1,12 +1,15 @@
package com.jacob.test.vbscript; package com.jacob.test.vbscript;
import com.jacob.com.*; import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComException;
import com.jacob.com.ComThread;
import com.jacob.com.DispatchEvents;
import com.jacob.com.Variant;
import com.jacob.test.BaseTestCase; import com.jacob.test.BaseTestCase;
import com.jacob.activeX.*;
/** /**
* In this case the component is created and used in the same thread * In this case the component is created and used in the same thread and it's an
* and it's an Apartment Threaded component, so we call InitSTA. * Apartment Threaded component, so we call InitSTA.
* <p> * <p>
* May need to run with some command line options (including from inside * May need to run with some command line options (including from inside
* Eclipse). Look in the docs area at the Jacob usage document for command line * Eclipse). Look in the docs area at the Jacob usage document for command line
@@ -24,7 +27,8 @@ public class ScriptTestActiveX extends BaseTestCase {
ScriptTestErrEvents te = new ScriptTestErrEvents(); ScriptTestErrEvents te = new ScriptTestErrEvents();
de = new DispatchEvents(sC, te); de = new DispatchEvents(sC, te);
if (de == null) { if (de == null) {
System.out.println("null returned when trying to create DispatchEvents"); System.out
.println("null returned when trying to create DispatchEvents");
} }
Variant result; Variant result;
result = sC.invoke("Eval", getSampleVPScriptForEval()); result = sC.invoke("Eval", getSampleVPScriptForEval());
@@ -32,15 +36,13 @@ public class ScriptTestActiveX extends BaseTestCase {
result = sC.invoke("Eval", getSampleVPScriptForEval()); result = sC.invoke("Eval", getSampleVPScriptForEval());
// call it 3 times to see the objects reused // call it 3 times to see the objects reused
result = sC.invoke("Eval", getSampleVPScriptForEval()); result = sC.invoke("Eval", getSampleVPScriptForEval());
System.out.println("eval("+getSampleVPScriptForEval()+") = "+ result); System.out.println("eval(" + getSampleVPScriptForEval() + ") = "
+ result);
} catch (ComException e) { } catch (ComException e) {
e.printStackTrace(); e.printStackTrace();
} } finally {
finally
{
Integer I = null; Integer I = null;
for(int i=1;i<1000000;i++) for (int i = 1; i < 1000000; i++) {
{
I = new Integer(i); I = new Integer(i);
} }
System.out.println(I); System.out.println(I);
@@ -49,4 +51,3 @@ public class ScriptTestActiveX extends BaseTestCase {
} }
} }
} }

View File

@@ -4,17 +4,16 @@ import com.jacob.com.Variant;
import com.jacob.test.BaseTestCase; import com.jacob.test.BaseTestCase;
/** /**
* Extracted from ScriptTest so everyone can see this * Extracted from ScriptTest so everyone can see this Made a test solely because
* Made a test solely because it made the ant test easier * it made the ant test easier
*/ */
public class ScriptTestErrEvents extends BaseTestCase { public class ScriptTestErrEvents extends BaseTestCase {
public void Error(Variant[] args) public void Error(Variant[] args) {
{
System.out.println("java callback for error!"); System.out.println("java callback for error!");
} }
public void Timeout(Variant[] args)
{ public void Timeout(Variant[] args) {
System.out.println("java callback for error!"); System.out.println("java callback for error!");
} }
} }

View File

@@ -8,7 +8,7 @@ package com.jacob.test.windowsmedia;
* May need to run with some command line options (including from inside Eclipse). * May need to run with some command line options (including from inside Eclipse).
* Look in the docs area at the Jacob usage document for command line options. * Look in the docs area at the Jacob usage document for command line options.
*/ */
import com.jacob.activeX.*; import com.jacob.activeX.ActiveXComponent;
import com.jacob.test.BaseTestCase; import com.jacob.test.BaseTestCase;
public class WMPlayer extends BaseTestCase { public class WMPlayer extends BaseTestCase {