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

194
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=".">
@@ -47,17 +47,19 @@
Now build up all the derived properties Now build up all the derived properties
================================================================== --> ================================================================== -->
<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.jar" value="jacob.jar" /> <property name="generated.filename.dll.x64" value="jacob-${version}-x64.dll" />
<property name="generated.filename.zip" value="jacob_${version}" /> <property name="generated.filename.jar" value="jacob.jar" />
<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,12 +430,12 @@
<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>
<zip <zip
destfile="${release.dir}/${generated.filename.zip}_src.zip"> destfile="${release.dir}/${generated.filename.zip}_src.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,62 +4,71 @@ 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.
* *
* @author joe * @author joe
* *
*/ */
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 <p.
* Derived from ample code found in Sun's java forums *
* <p. * @return true if the native library has loaded, false if there was a
* @return true if the native library has loaded, false if there was a problem. * 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.
FileOutputStream outputStream = new FileOutputStream(temporaryDll); // this code might be different if you customize the name of
byte[] array = new byte[8192]; // the jacob dll to match some custom naming convention
for (int i = inputStream.read(array); InputStream inputStream = getClass().getResource(
i != -1; "/" + LibraryLoader.getPreferredDLLName() + ".dll")
i = inputStream.read(array)) { .openStream();
outputStream.write(array, 0, i); // Put the DLL somewhere we can find it with a name Jacob expects
} File temporaryDll = File.createTempFile(LibraryLoader
outputStream.close(); .getPreferredDLLName(), ".dll");
temporaryDll.deleteOnExit(); FileOutputStream outputStream = new FileOutputStream(temporaryDll);
System.load(temporaryDll.getPath()); byte[] array = new byte[8192];
return true; for (int i = inputStream.read(array); i != -1; i = inputStream
} .read(array)) {
catch(Throwable e) outputStream.write(array, 0, i);
{ }
e.printStackTrace(); outputStream.close();
return false; temporaryDll.deleteOnExit();
} // 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;
} catch (Throwable e) {
e.printStackTrace();
return false;
}
}
} }

View File

@@ -1,25 +1,38 @@
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();
} }
public MathTest(){ /** default constructor */
public MathTest() {
} }
public void runTest(){ /**
* not clear why we need a class and run method but that's the way it was
* written
*/
public void runTest() {
// deprecated // deprecated
// System.runFinalizersOnExit(true); // System.runFinalizersOnExit(true);
Dispatch test = new ActiveXComponent("MathTest.Math"); Dispatch test = new ActiveXComponent("MathTest.Math");
@@ -42,14 +55,29 @@ class MathTest {
System.out.println("v.toDispatch=" + v.toDispatch()); System.out.println("v.toDispatch=" + v.toDispatch());
} }
public class TestEvents { /**
public void DoneAdd(Variant[] args) { *
System.out.println("DoneAdd called in java"); * sample class to catch the events
*
*/
public class TestEvents {
/**
* catches the DoneAdd event
*
* @param args
*/
public void DoneAdd(Variant[] args) {
System.out.println("DoneAdd called in java");
}
/**
* catches the DoneMult event
*
* @param args
*/
public void DoneMult(Variant[] args) {
System.out.println("DoneMult called in java");
}
} }
public void DoneMult(Variant[] args) {
System.out.println("DoneMult called in java");
}
}
} }

View File

@@ -19,123 +19,126 @@
*/ */
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"); // my xp box with a later release of access needed this
// my xp box with a later release of access needed this ActiveXComponent ax = new ActiveXComponent("DAO.PrivateDBEngine.35");
ActiveXComponent ax = new ActiveXComponent("DAO.PrivateDBEngine.35"); // 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
// this works when running in eclipse because the test cases run pwd project root // 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
Dispatch qd = Dispatch.call(db, "CreateQueryDef","").toDispatch(); Dispatch qd = Dispatch.call(db, "CreateQueryDef", "").toDispatch();
// set the SQL string on it // set the SQL string on it
Dispatch.put(qd, "SQL", sql); Dispatch.put(qd, "SQL", sql);
Variant result = getByQueryDef(qd); Variant result = getByQueryDef(qd);
// the 2-d safearray is transposed from what you might expect // the 2-d safearray is transposed from what you might expect
System.out.println("resulting array is "+result.toSafeArray()); System.out.println("resulting array is " + result.toSafeArray());
close(db); close(db);
System.out.println("about to call ComThread.Release()"); System.out.println("about to call ComThread.Release()");
ComThread.Release(); ComThread.Release();
} }
/** /**
* Open a database * Open a database
* @param ax *
* @param fileName * @param ax
* @return dispatch object that was opened * @param fileName
*/ * @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 };
Dispatch openDB = ax.invoke("OpenDatabase", args).toDispatch(); Dispatch openDB = ax.invoke("OpenDatabase", args).toDispatch();
return openDB; return openDB;
} }
/** /**
* Close a database * Close a database
* @param openDB db to be closed *
*/ * @param openDB
public static void close(Dispatch openDB) * db to be closed
{ */
Dispatch.call(openDB, "Close"); public static void close(Dispatch openDB) {
} Dispatch.call(openDB, "Close");
}
/** /**
* Extract the values from the recordset * Extract the values from the recordset
* @param recset *
* @return Variant that is the returned values * @param recset
*/ * @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);
return v; return v;
} }
/** /**
* should return ?? for the passed in ?? * should return ?? for the passed in ??
* @param qd *
* @return Variant results of query? * @param qd
*/ * @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(""); Variant vals = getValues(recset);
Variant vals = getValues(recset); return vals;
return vals; }
}
/** /**
* gets the columns form the rec set * gets the columns form the rec set
* @param recset *
* @return list of column names * @param recset
*/ * @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];
Variant vi = new Variant(); Variant vi = new Variant();
for (int i=0;i<n_flds;i++) { for (int i = 0; i < n_flds; i++) {
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();
} }
return s; return s;
} }
} }

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.
{ *
super("ADODB.Command"); */
} public class Command extends Dispatch {
/**
* standard constructor
*/
public 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 Dispatch.get(this, "Properties"); *
} * @return the properties
*/
public Variant getProperties() {
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
Dispatch.put(this, "ActiveConnection", ppvObject); *
} * @param ppvObject
* the new connection
*/
public void setActiveConnection(Connection ppvObject) {
Dispatch.put(this, "ActiveConnection", ppvObject);
}
public String getCommandText() /**
{ *
return Dispatch.get(this, "CommandText").toString(); * @return the results from "CommandText"
} */
public String getCommandText() {
return Dispatch.get(this, "CommandText").toString();
}
public void setCommandText(String pbstr) /**
{ *
Dispatch.put(this, "CommandText", pbstr); * @param pbstr
} * the new "CommandText"
*/
public void setCommandText(String pbstr) {
Dispatch.put(this, "CommandText", pbstr);
}
public int getCommandTimeout() /**
{ *
return Dispatch.get(this, "CommandTimeout").getInt(); * @return the results of "CommandTimeout"
} */
public int getCommandTimeout() {
return Dispatch.get(this, "CommandTimeout").getInt();
}
public void setCommandTimeout(int plTimeout) /**
{ *
Dispatch.put(this, "CommandTimeout", new Variant(plTimeout)); * @param plTimeout
} * the new "CommandTimeout"
*/
public void setCommandTimeout(int plTimeout) {
Dispatch.put(this, "CommandTimeout", new Variant(plTimeout));
}
public boolean getPrepared() /**
{ *
return Dispatch.get(this, "Prepared").getBoolean(); * @return results from "Prepared"
} */
public boolean getPrepared() {
return Dispatch.get(this, "Prepared").getBoolean();
}
public void setPrepared(boolean pfPrepared) /**
{ *
Dispatch.put(this, "Prepared", new Variant(pfPrepared)); * @param pfPrepared
} * the new value for "Prepared"
*/
public void setPrepared(boolean 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
Variant dummy = new Variant(); *
return new Recordset(Dispatch.call(this, "Execute", dummy).toDispatch()); * @return
} */
public Recordset Execute() {
Variant dummy = new Variant();
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"
return Dispatch.get(this, "Parameters"); */
} public Variant getParameters() {
return Dispatch.get(this, "Parameters");
}
public void setCommandType(int plCmdType) /**
{ *
Dispatch.put(this, "CommandType", new Variant(plCmdType)); * @param plCmdType
} * new "CommandType"
*/
public void setCommandType(int plCmdType) {
Dispatch.put(this, "CommandType", new Variant(plCmdType));
}
public int getCommandType() /**
{ *
return Dispatch.get(this, "CommandType").getInt(); * @return current "CommandType"
} */
public int getCommandType() {
return Dispatch.get(this, "CommandType").getInt();
}
public String getName() /**
{ *
return Dispatch.get(this, "Name").toString(); * @return "Name"
} */
public String getName() {
return Dispatch.get(this, "Name").toString();
}
public void setName(String pbstrName) /**
{ *
Dispatch.put(this, "Name", pbstrName); * @param pbstrName
} * new "Name"
*/
public void setName(String pbstrName) {
Dispatch.put(this, "Name", pbstrName);
}
public int getState() /**
{ *
return Dispatch.get(this, "State").getInt(); * @return curent "State"
} */
public int getState() {
return Dispatch.get(this, "State").getInt();
}
public void Cancel() /**
{ * cancel whatever it is we're doing
Dispatch.call(this, "Cancel"); */
} public void Cancel() {
Dispatch.call(this, "Cancel");
}
} }

View File

@@ -2,13 +2,12 @@ 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; public static final int adCmdTable = 2;
public static final int adCmdTable = 2; public static final int adCmdStoredProc = 4;
public static final int adCmdStoredProc = 4; public static final int adCmdFile = 256;
public static final int adCmdFile = 256; public static final int adCmdTableDirect = 512;
public static final int adCmdTableDirect = 512;
} }

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,122 +1,101 @@
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()
{
return Dispatch.get(this, "ActualSize").getInt();
} }
public int getAttributes() public int getActualSize() {
{ return Dispatch.get(this, "ActualSize").getInt();
return Dispatch.get(this, "Attributes").getInt();
} }
public int getDefinedSize() public int getAttributes() {
{ return Dispatch.get(this, "Attributes").getInt();
return Dispatch.get(this, "DefinedSize").getInt();
} }
public String getName() public int getDefinedSize() {
{ return Dispatch.get(this, "DefinedSize").getInt();
return Dispatch.get(this, "Name").toString();
} }
public int getType() public String getName() {
{ return Dispatch.get(this, "Name").toString();
return Dispatch.get(this, "Type").getInt();
} }
public Variant getValue() public int getType() {
{ return Dispatch.get(this, "Type").getInt();
return Dispatch.get(this, "Value");
} }
public void setValue(Variant pvar) public Variant getValue() {
{ return Dispatch.get(this, "Value");
Dispatch.put(this, "Value", pvar);
} }
public byte getPrecision() public void setValue(Variant pvar) {
{ Dispatch.put(this, "Value", pvar);
return Dispatch.get(this, "Precision").getByte();
} }
public byte getNumericScale() public byte getPrecision() {
{ return Dispatch.get(this, "Precision").getByte();
return Dispatch.get(this, "NumericScale").getByte();
} }
public void AppendChunk(Variant Data) public byte getNumericScale() {
{ return Dispatch.get(this, "NumericScale").getByte();
Dispatch.call(this, "AppendChunk", Data);
} }
public Variant GetChunk(int Length) public void AppendChunk(Variant Data) {
{ Dispatch.call(this, "AppendChunk", Data);
return Dispatch.call(this, "GetChunk", new Variant(Length));
} }
public Variant getOriginalValue() public Variant GetChunk(int Length) {
{ return Dispatch.call(this, "GetChunk", new Variant(Length));
return Dispatch.get(this, "OriginalValue");
} }
public Variant getUnderlyingValue() public Variant getOriginalValue() {
{ return Dispatch.get(this, "OriginalValue");
return Dispatch.get(this, "UnderlyingValue");
} }
public Variant getDataFormat() public Variant getUnderlyingValue() {
{ return Dispatch.get(this, "UnderlyingValue");
return Dispatch.get(this, "DataFormat");
} }
public void setDataFormat(Variant ppiDF) public Variant getDataFormat() {
{ return Dispatch.get(this, "DataFormat");
Dispatch.put(this, "DataFormat", ppiDF);
} }
public void setPrecision(byte pb) public void setDataFormat(Variant ppiDF) {
{ Dispatch.put(this, "DataFormat", ppiDF);
Dispatch.put(this, "Precision", new Variant(pb));
} }
public void setNumericScale(byte pb) public void setPrecision(byte pb) {
{ Dispatch.put(this, "Precision", new Variant(pb));
Dispatch.put(this, "NumericScale", new Variant(pb));
} }
public void setType(int pDataType) public void setNumericScale(byte pb) {
{ Dispatch.put(this, "NumericScale", new Variant(pb));
Dispatch.put(this, "Type", new Variant(pDataType));
} }
public void setDefinedSize(int pl) public void setType(int pDataType) {
{ Dispatch.put(this, "Type", new Variant(pDataType));
Dispatch.put(this, "DefinedSize", new Variant(pl));
} }
public void setAttributes(int pl) public void setDefinedSize(int pl) {
{ Dispatch.put(this, "DefinedSize", new Variant(pl));
Dispatch.put(this, "Attributes", new Variant(pl)); }
public void setAttributes(int pl) {
Dispatch.put(this, "Attributes", new Variant(pl));
} }
} }

View File

@@ -1,48 +1,43 @@
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 {
super("ADODB.Recordset"); public 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()
{
return Dispatch.get(this, "AbsolutePosition").getInt();
} }
public void setAbsolutePosition(int pl) public int getAbsolutePosition() {
{ return Dispatch.get(this, "AbsolutePosition").getInt();
Dispatch.put(this, "AbsolutePosition", new Variant(pl));
} }
public Connection getActiveConnection() public void setAbsolutePosition(int pl) {
{ Dispatch.put(this, "AbsolutePosition", new Variant(pl));
return new Connection(Dispatch.get(this, "ActiveConnection").toDispatch());
}
public void setActiveConnection(Connection ppvObject)
{
Dispatch.put(this, "ActiveConnection", ppvObject);
}
public void setActiveConnection(Variant ppvObject)
{
Dispatch.put(this, "ActiveConnection", ppvObject);
}
public boolean getBOF()
{
return Dispatch.get(this, "BOF").getBoolean();
} }
public Variant getBookmark() public Connection getActiveConnection() {
{ return new Connection(Dispatch.get(this, "ActiveConnection")
return Dispatch.get(this, "Bookmark"); .toDispatch());
} }
public void setBookmark(Variant pvBookmark) public void setActiveConnection(Connection ppvObject) {
{ Dispatch.put(this, "ActiveConnection", ppvObject);
Dispatch.put(this, "Bookmark", pvBookmark);
} }
public int getCacheSize() public void setActiveConnection(Variant ppvObject) {
{ Dispatch.put(this, "ActiveConnection", ppvObject);
return Dispatch.get(this, "CacheSize").getInt();
} }
public void setCacheSize(int pl) public boolean getBOF() {
{ return Dispatch.get(this, "BOF").getBoolean();
Dispatch.put(this, "CacheSize", new Variant(pl));
} }
public int getCursorType() public Variant getBookmark() {
{ return Dispatch.get(this, "Bookmark");
return Dispatch.get(this, "CursorType").getInt();
} }
public void setCursorType(int pl) public void setBookmark(Variant pvBookmark) {
{ Dispatch.put(this, "Bookmark", pvBookmark);
Dispatch.put(this, "CursorType", new Variant(pl));
} }
public boolean getEOF() public int getCacheSize() {
{ return Dispatch.get(this, "CacheSize").getInt();
return Dispatch.get(this, "EOF").getBoolean();
}
public Fields getFields()
{
return new Fields(Dispatch.get(this, "Fields").toDispatch());
} }
public int getLockType() public void setCacheSize(int pl) {
{ Dispatch.put(this, "CacheSize", new Variant(pl));
return Dispatch.get(this, "LockType").getInt();
} }
public void setLockType(int plLockType) public int getCursorType() {
{ return Dispatch.get(this, "CursorType").getInt();
Dispatch.put(this, "LockType", new Variant(plLockType));
} }
public int getMaxRecords() public void setCursorType(int pl) {
{ Dispatch.put(this, "CursorType", new Variant(pl));
return Dispatch.get(this, "MaxRecords").getInt();
} }
public void setMaxRecords(int pl) public boolean getEOF() {
{ return Dispatch.get(this, "EOF").getBoolean();
Dispatch.put(this, "MaxRecords", new Variant(pl));
} }
public int getRecordCount() public Fields getFields() {
{ return new Fields(Dispatch.get(this, "Fields").toDispatch());
return Dispatch.get(this, "RecordCount").getInt();
} }
public void setSource(Object pvSource) public int getLockType() {
{ return Dispatch.get(this, "LockType").getInt();
Dispatch.put(this, "Source", pvSource);
} }
public void setSource(String pvSource) public void setLockType(int plLockType) {
{ Dispatch.put(this, "LockType", new Variant(plLockType));
Dispatch.put(this, "Source", pvSource);
} }
public Variant getSource() public int getMaxRecords() {
{ return Dispatch.get(this, "MaxRecords").getInt();
return Dispatch.get(this, "Source");
} }
public void AddNew(Variant FieldList, Variant Values) public void setMaxRecords(int pl) {
{ Dispatch.put(this, "MaxRecords", new Variant(pl));
Dispatch.call(this, "AddNew", FieldList, Values);
} }
public void CancelUpdate() public int getRecordCount() {
{ return Dispatch.get(this, "RecordCount").getInt();
Dispatch.call(this, "CancelUpdate");
} }
public void Close() public void setSource(Object pvSource) {
{ Dispatch.put(this, "Source", pvSource);
Dispatch.call(this, "Close");
} }
public void Delete(int AffectRecords) public void setSource(String pvSource) {
{ Dispatch.put(this, "Source", pvSource);
Dispatch.call(this, "Delete", new Variant(AffectRecords));
} }
public Variant GetRows(int Rows, Variant Start, Variant Fields) public Variant getSource() {
{ return Dispatch.get(this, "Source");
return Dispatch.call(this, "GetRows", new Variant(Rows), Start, Fields); }
public void AddNew(Variant FieldList, Variant Values) {
Dispatch.call(this, "AddNew", FieldList, Values);
}
public void CancelUpdate() {
Dispatch.call(this, "CancelUpdate");
}
public void Close() {
Dispatch.call(this, "Close");
}
public void Delete(int AffectRecords) {
Dispatch.call(this, "Delete", new Variant(AffectRecords));
}
public Variant GetRows(int Rows, Variant Start, Variant 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)
{
Dispatch.call(this, "Find", Criteria, new Variant(SkipRecords), new Variant(SearchDirection), Start);
} }
public void Cancel() public void Find(String Criteria, int SkipRecords, int SearchDirection,
{ Variant Start) {
Dispatch.call(this, "Cancel"); Dispatch.call(this, "Find", Criteria, new Variant(SkipRecords),
new Variant(SearchDirection), Start);
} }
public Variant getDataSource() public void Cancel() {
{ Dispatch.call(this, "Cancel");
return Dispatch.get(this, "DataSource");
} }
public void setDataSource(Variant ppunkDataSource) public Variant getDataSource() {
{ return Dispatch.get(this, "DataSource");
Dispatch.put(this, "DataSource", ppunkDataSource);
} }
public void Save(String FileName, int PersistFormat) public void setDataSource(Variant ppunkDataSource) {
{ Dispatch.put(this, "DataSource", ppunkDataSource);
Dispatch.call(this, "Save", FileName, new Variant(PersistFormat));
} }
public Variant getActiveCommand() public void Save(String FileName, int PersistFormat) {
{ Dispatch.call(this, "Save", FileName, new Variant(PersistFormat));
return Dispatch.get(this, "ActiveCommand");
} }
public void setStayInSync(boolean pb) public Variant getActiveCommand() {
{ return Dispatch.get(this, "ActiveCommand");
Dispatch.put(this, "StayInSync", new Variant(pb));
} }
public boolean getStayInSync() public void setStayInSync(boolean pb) {
{ Dispatch.put(this, "StayInSync", new Variant(pb));
return Dispatch.get(this, "StayInSync").getBoolean();
} }
public String GetString(int StringFormat, int NumRows, String ColumnDelimeter, String RowDelimeter, String NullExpr) public boolean getStayInSync() {
{ return Dispatch.get(this, "StayInSync").getBoolean();
return Dispatch.call(this, "GetString", new Variant(StringFormat),
new Variant(NumRows), ColumnDelimeter, RowDelimeter, NullExpr).toString();
} }
public String getDataMember() public String GetString(int StringFormat, int NumRows,
{ String ColumnDelimeter, String RowDelimeter, String NullExpr) {
return Dispatch.get(this, "DataMember").toString(); return Dispatch.call(this, "GetString", new Variant(StringFormat),
new Variant(NumRows), ColumnDelimeter, RowDelimeter, NullExpr)
.toString();
} }
public void setDataMember(String pl) public String getDataMember() {
{ return Dispatch.get(this, "DataMember").toString();
Dispatch.put(this, "DataMember", new Variant(pl));
} }
public int CompareBookmarks(Variant Bookmark1, Variant Bookmark2) public void setDataMember(String pl) {
{ Dispatch.put(this, "DataMember", new Variant(pl));
return Dispatch.call(this, "CompareBookmarks", Bookmark1, Bookmark2).getInt();
} }
public Recordset Clone(int LockType) public int CompareBookmarks(Variant Bookmark1, Variant Bookmark2) {
{ return Dispatch.call(this, "CompareBookmarks", Bookmark1, Bookmark2)
return new Recordset(Dispatch.call(this, "Clone", .getInt();
new Variant(LockType)).toDispatch());
} }
public void Resync(int AffectRecords, int ResyncValues) public Recordset Clone(int LockType) {
{ return new Recordset(Dispatch
Dispatch.call(this, "Resync", new Variant(AffectRecords), new Variant(ResyncValues)); .call(this, "Clone", new Variant(LockType)).toDispatch());
} }
public void Seek(Variant KeyValues, int SeekOption) public void Resync(int AffectRecords, int ResyncValues) {
{ Dispatch.call(this, "Resync", new Variant(AffectRecords), new Variant(
Dispatch.call(this, "Seek", KeyValues, new Variant(SeekOption)); ResyncValues));
} }
public void setIndex(String pl) public void Seek(Variant KeyValues, int SeekOption) {
{ Dispatch.call(this, "Seek", KeyValues, new Variant(SeekOption));
Dispatch.put(this, "Index", new Variant(pl));
} }
public String getIndex() public void setIndex(String pl) {
{ Dispatch.put(this, "Index", new Variant(pl));
return Dispatch.get(this, "Index)").toString(); }
public String getIndex() {
return Dispatch.get(this, "Index)").toString();
} }
} }

View File

@@ -1,63 +1,56 @@
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)
{
Fields fs = rs.getFields();
for (int i=0;i<fs.getCount();i++) public class test {
{ public static void printRS(Recordset rs) {
System.out.print(fs.getItem(i).getName() + " "); Fields fs = rs.getFields();
}
System.out.println("");
rs.MoveFirst(); for (int i = 0; i < fs.getCount(); i++) {
while (!rs.getEOF()) System.out.print(fs.getItem(i).getName() + " ");
{ }
for(int i=0;i<fs.getCount();i++) System.out.println("");
{
Field f = fs.getItem(i); rs.MoveFirst();
Variant v = f.getValue(); while (!rs.getEOF()) {
System.out.print(v + " "); for (int i = 0; i < fs.getCount(); i++) {
} Field f = fs.getItem(i);
System.out.println(""); Variant v = f.getValue();
rs.MoveNext(); System.out.print(v + " ");
} }
} System.out.println("");
rs.MoveNext();
}
}
// 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));
printRS(rs); printRS(rs);
} }
// 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); c.Open();
c.Open(); Command comm = new Command();
Command comm = new Command(); comm.setActiveConnection(c);
comm.setActiveConnection(c); comm.setCommandType(CommandTypeEnum.adCmdText);
comm.setCommandType(CommandTypeEnum.adCmdText); comm.setCommandText(query);
comm.setCommandText(query); Recordset rs = comm.Execute();
Recordset rs = comm.Execute(); printRS(rs);
printRS(rs); 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); getRS(connectStr, queryStr);
getRS(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,14 +1,23 @@
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
//System.runFinalizersOnExit(true); // do
// System.runFinalizersOnExit(true);
ActiveXComponent mf = new ActiveXComponent("MultiFace.Face"); ActiveXComponent mf = new ActiveXComponent("MultiFace.Face");
try { try {

View File

@@ -1,46 +1,52 @@
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
ComThread.InitSTA(); *
* @param args
ActiveXComponent xl = new ActiveXComponent("Excel.Application"); * standard command line arguments
try { */
System.out.println("version="+xl.getProperty("Version")); public static void main(String[] args) {
System.out.println("version="+Dispatch.get(xl, "Version")); ComThread.InitSTA();
Dispatch.put(xl, "Visible", new Variant(true));
Dispatch workbooks = xl.getProperty("Workbooks").toDispatch(); ActiveXComponent xl = new ActiveXComponent("Excel.Application");
Dispatch workbook = Dispatch.get(workbooks,"Add").toDispatch(); try {
Dispatch sheet = Dispatch.get(workbook,"ActiveSheet").toDispatch(); System.out.println("version=" + xl.getProperty("Version"));
Dispatch a1 = Dispatch.invoke(sheet, "Range", Dispatch.Get, System.out.println("version=" + Dispatch.get(xl, "Version"));
new Object[] {"A1"}, Dispatch.put(xl, "Visible", new Variant(true));
new int[1]).toDispatch(); Dispatch workbooks = xl.getProperty("Workbooks").toDispatch();
Dispatch a2 = Dispatch.invoke(sheet, "Range", Dispatch.Get, Dispatch workbook = Dispatch.get(workbooks, "Add").toDispatch();
new Object[] {"A2"}, Dispatch sheet = Dispatch.get(workbook, "ActiveSheet").toDispatch();
new int[1]).toDispatch(); Dispatch a1 = Dispatch.invoke(sheet, "Range", Dispatch.Get,
Dispatch.put(a1, "Value", "123.456"); new Object[] { "A1" }, new int[1]).toDispatch();
Dispatch.put(a2, "Formula", "=A1*2"); Dispatch a2 = Dispatch.invoke(sheet, "Range", Dispatch.Get,
System.out.println("a1 from excel:"+Dispatch.get(a1, "Value")); new Object[] { "A2" }, new int[1]).toDispatch();
System.out.println("a2 from excel:"+Dispatch.get(a2, "Value")); Dispatch.put(a1, "Value", "123.456");
Variant f = new Variant(false); Dispatch.put(a2, "Formula", "=A1*2");
Dispatch.call(workbook, "Close", f); System.out.println("a1 from excel:" + Dispatch.get(a1, "Value"));
} catch (Exception e) { System.out.println("a2 from excel:" + Dispatch.get(a2, "Value"));
e.printStackTrace(); Variant f = new Variant(false);
} finally { Dispatch.call(workbook, "Close", f);
xl.invoke("Quit", new Variant[] {}); } catch (Exception e) {
ComThread.Release(); e.printStackTrace();
} } finally {
} xl.invoke("Quit", new Variant[] {});
ComThread.Release();
}
}
} }

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

@@ -14,150 +14,152 @@ import com.jacob.com.Variant;
* are sections that could be enhanced * are sections that could be enhanced
*/ */
public class WordDocumentProperties { public class WordDocumentProperties {
//Declare word object // Declare word object
private ActiveXComponent objWord; private ActiveXComponent objWord;
//Declare Word Properties // Declare Word Properties
private Dispatch custDocprops; private Dispatch custDocprops;
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
//private Dispatch documents; // use it
// private Dispatch documents;
private Dispatch document; private Dispatch document;
private Dispatch wordObject; private Dispatch wordObject;
/** /**
* Empty Constructor * Empty Constructor
* *
*/ */
public WordDocumentProperties() { public WordDocumentProperties() {
} }
/** /**
* Opens a document * Opens a document
* *
* @param filename * @param filename
*/ */
public void open(String filename) { public void open(String filename) {
//Instantiate objWord // Instantiate objWord
objWord = new ActiveXComponent("Word.Application"); objWord = new ActiveXComponent("Word.Application");
//Assign a local word object // Assign a local word object
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();
//Open a word document, Current Active Document // Open a word document, Current Active Document
document = Dispatch.call(documents, "Open", filename).toDispatch(); document = Dispatch.call(documents, "Open", filename).toDispatch();
} }
/** /**
* Creates an instance of the VBA CustomDocumentProperties property * Creates an instance of the VBA CustomDocumentProperties property
* *
*/ */
public void selectCustomDocumentProperitiesMode() { public void selectCustomDocumentProperitiesMode() {
//Create CustomDocumentProperties and BuiltInDocumentProperties // Create CustomDocumentProperties and BuiltInDocumentProperties
// properties // properties
custDocprops = Dispatch.get(document, "CustomDocumentProperties") custDocprops = Dispatch.get(document, "CustomDocumentProperties")
.toDispatch(); .toDispatch();
} }
/** /**
* Creates an instance of the VBA BuiltInDocumentProperties property * Creates an instance of the VBA BuiltInDocumentProperties property
* *
*/ */
public void selectBuiltinPropertiesMode() { public void selectBuiltinPropertiesMode() {
//Create CustomDocumentProperties and BuiltInDocumentProperties // Create CustomDocumentProperties and BuiltInDocumentProperties
// properties // properties
builtInDocProps = Dispatch.get(document, "BuiltInDocumentProperties") builtInDocProps = Dispatch.get(document, "BuiltInDocumentProperties")
.toDispatch(); .toDispatch();
} }
/** /**
* Closes a document * Closes a document
* *
*/ */
public void close() { public void close() {
//Close object // Close object
Dispatch.call(document, "Close"); Dispatch.call(document, "Close");
} }
/** /**
* Custom Property Name is passed in * Custom Property Name is passed in
* *
* @param cusPropName * @param cusPropName
* @return String - Custom property value * @return String - Custom property value
*/ */
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;
} }
return cusPropName; return cusPropName;
} }
/** /**
* Built In Property Name is passed in * Built In Property Name is passed in
* *
* @param builtInPropName * @param builtInPropName
* @return String - Built in property value * @return String - Built in property value
*/ */
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
builtInPropName = null; builtInPropName = null;
} }
return builtInPropName; return builtInPropName;
} }
/** /**
* 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) { */
try { public static void main(String[] args) {
//Instantiate the class try {
WordDocumentProperties jacTest = new WordDocumentProperties(); // Instantiate the class
WordDocumentProperties jacTest = new WordDocumentProperties();
//Open the word doc // Open the word doc
jacTest.open("\\\\Saturn\\documentstorage\\s.doc"); jacTest.open("\\\\Saturn\\documentstorage\\s.doc");
//Set Custom Properties // Set Custom Properties
jacTest.selectCustomDocumentProperitiesMode(); jacTest.selectCustomDocumentProperitiesMode();
//Set Built In Properties // Set Built In Properties
jacTest.selectBuiltinPropertiesMode(); jacTest.selectBuiltinPropertiesMode();
//Get custom Property Value // Get custom Property Value
String custValue = jacTest.getCustomProperty("Information Source"); String custValue = jacTest.getCustomProperty("Information Source");
//Get built in prroperty Property Value // Get built in prroperty Property Value
String builtInValue = jacTest.getBuiltInProperty("Author"); String builtInValue = jacTest.getBuiltInProperty("Author");
//Close Word Doc // Close Word Doc
jacTest.close(); jacTest.close();
//Output data // Output data
System.out.println("Document Val One: " + custValue); System.out.println("Document Val One: " + custValue);
System.out.println("Document Author: " + builtInValue); System.out.println("Document Author: " + builtInValue);
} catch (Exception e) { } catch (Exception e) {
System.out.println(e); System.out.println(e);
} }
} }
} }

View File

@@ -5,65 +5,76 @@ 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) {
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
while(sb.length() < i) { while (sb.length() < i) {
sb.append(' '); sb.append(' ');
} }
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;
}
Dispatch oFolders = Dispatch.get(o, "Folders").toDispatch();
// System.out.println("oFolders=" + oFolders);
if (oFolders == null) {
return;
}
if (o == null) return; Dispatch oFolder = Dispatch.get(oFolders, "GetFirst").toDispatch();
Dispatch oFolders = Dispatch.get(o, "Folders").toDispatch(); do {
// System.out.println("oFolders=" + oFolders); Object oFolderName = Dispatch.get(oFolder, "Name");
if (oFolders == null) return; if (null == oFolderName) {
break;
}
Dispatch oFolder = Dispatch.get(oFolders, "GetFirst").toDispatch(); System.out.println(pad(iIndent) + oFolderName);
do { recurseFolders(iIndent + 3, oFolder);
Object oFolderName = Dispatch.get(oFolder, "Name");
if (null == oFolderName) {
break;
}
System.out.println(pad(iIndent) + oFolderName); oFolder = Dispatch.get(oFolders, "GetNext").toDispatch();
recurseFolders(iIndent + 3, oFolder); } while (true);
oFolder = Dispatch.get(oFolders, "GetNext").toDispatch(); }
} while(true);
} /**
* standard run loop
*
* @param asArgs
* command line arguments
* @throws Exception
*/
public static void main(String asArgs[]) throws Exception {
System.out.println("Outlook: IN");
ActiveXComponent axOutlook = new ActiveXComponent("Outlook.Application");
try {
System.out.println("version=" + axOutlook.getProperty("Version"));
public static void main(String asArgs[]) throws Exception { Dispatch oOutlook = axOutlook.getObject();
System.out.println("Outlook: IN"); System.out.println("version=" + Dispatch.get(oOutlook, "Version"));
ActiveXComponent axOutlook = new ActiveXComponent("Outlook.Application"); Dispatch oNameSpace = axOutlook.getProperty("Session").toDispatch();
try { System.out.println("oNameSpace=" + oNameSpace);
System.out.println("version="+axOutlook.getProperty("Version"));
Dispatch oOutlook = axOutlook.getObject(); recurseFolders(0, oNameSpace);
System.out.println("version="+Dispatch.get(oOutlook, "Version"));
Dispatch oNameSpace = axOutlook.getProperty("Session").toDispatch(); } finally {
System.out.println("oNameSpace=" + oNameSpace); axOutlook.invoke("Quit", new Variant[] {});
}
recurseFolders(0, oNameSpace); }
} finally {
axOutlook.invoke("Quit", new Variant[] {});
}
}
} }

View File

@@ -10,41 +10,49 @@ 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
*
*/ */
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;
/** the dispatch that points at the drive this DiskUtil operates against */ /** the dispatch that points at the drive this DiskUtil operates against */
private Dispatch myDrive = null; private Dispatch myDrive = null;
/** /**
* 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);
} }
/** /**
* 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();
} }
} }
@@ -54,58 +62,61 @@ public class DiskUtils {
public void tearDown() { public void tearDown() {
ComThread.Release(); ComThread.Release();
} }
/** /**
* convenience method * convenience method
*
* @return driver serial number * @return driver serial number
*/ */
public int getSerialNumber() { public int getSerialNumber() {
return Dispatch.get(myDrive, "SerialNumber").getInt(); return Dispatch.get(myDrive, "SerialNumber").getInt();
} }
/** /**
* 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() {
Variant returnValue = Dispatch.get(myDrive, "TotalSize"); Variant returnValue = Dispatch.get(myDrive, "TotalSize");
if (returnValue.getvt() == Variant.VariantDouble){ if (returnValue.getvt() == Variant.VariantDouble) {
return sizeFormatter.format(returnValue.getDouble()); return sizeFormatter.format(returnValue.getDouble());
} else if (returnValue.getvt() == Variant.VariantInt){ } else if (returnValue.getvt() == Variant.VariantInt) {
return sizeFormatter.format(returnValue.getInt()); return sizeFormatter.format(returnValue.getInt());
} else { } else {
return "Don't know type: "+returnValue.getvt(); return "Don't know type: " + returnValue.getvt();
} }
} }
/** /**
* 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() {
Variant returnValue = Dispatch.get(myDrive, "FreeSpace"); Variant returnValue = Dispatch.get(myDrive, "FreeSpace");
if (returnValue.getvt() == Variant.VariantDouble){ if (returnValue.getvt() == Variant.VariantDouble) {
return sizeFormatter.format(returnValue.getDouble()); return sizeFormatter.format(returnValue.getDouble());
} else if (returnValue.getvt() == Variant.VariantInt){ } else if (returnValue.getvt() == Variant.VariantInt) {
return sizeFormatter.format(returnValue.getInt()); return sizeFormatter.format(returnValue.getInt());
} else { } else {
return "Don't know type: "+returnValue.getvt(); return "Don't know type: " + returnValue.getvt();
} }
} }
/** /**
* *
* @return file system on the drive * @return file system on the drive
*/ */
public String getFileSystemType() { public String getFileSystemType() {
//figure ot the actual variant type // figure ot the actual variant type
//Variant returnValue = Dispatch.get(myDrive, "FileSystem"); // Variant returnValue = Dispatch.get(myDrive, "FileSystem");
//System.out.println(returnValue.getvt()); // System.out.println(returnValue.getvt());
return Dispatch.get(myDrive, "FileSystem").getString(); return Dispatch.get(myDrive, "FileSystem").getString();
} }
@@ -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("Volume Name is: "+ utilConnection.getVolumeName()); System.out.println("FileSystem is: "
System.out.println("Disk total size is: "+ utilConnection.getTotalSize()); + utilConnection.getFileSystemType());
System.out.println("Disk free space is: "+ utilConnection.getFreeSpace()); System.out.println("Volume Name is: " + utilConnection.getVolumeName());
System.out.println("Disk total size is: "
+ utilConnection.getTotalSize());
System.out.println("Disk free space is: "
+ utilConnection.getFreeSpace());
utilConnection.tearDown(); utilConnection.tearDown();
} }
} }

View File

@@ -13,23 +13,27 @@ import com.jacob.com.Variant;
* fold, spindled and mutilated by clay_shooter * fold, spindled and mutilated by clay_shooter
* *
* @author chris_knowles * @author chris_knowles
* *
*/ */
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.
String query = "select CategoryString, Message, TimeGenerated, User, Type " String query = "select CategoryString, Message, TimeGenerated, User, Type "
+ "from Win32_NtLogEvent " + "from Win32_NtLogEvent "
+ "where Logfile = 'Application' and TimeGenerated > '20070915000000.000000-***'"; + "where Logfile = 'Application' and TimeGenerated > '20070915000000.000000-***'";
Variant vCollection = wmiconnect Variant vCollection = wmiconnect
.invoke("ExecQuery", new Variant(query)); .invoke("ExecQuery", new Variant(query));
@@ -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,85 +1,121 @@
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 {
super("Visio.Application");
setVisible(false);
}
public VisioApp() throws VisioException { /**
super("Visio.Application"); * creates a DispatchEvents object to register o as a listener
setVisible(false); *
} * @param o
*/
public void addEventListener(VisioEventListener o) {
DispatchEvents events = new DispatchEvents(this, o);
if (events == null) {
System.out
.println("You should never get null back when creating a DispatchEvents object");
}
}
/** /**
* creates a DispatchEvents boject to register o as a listener * opens the passed in file in Visio
* @param o *
*/ * @param f
public void addEventListener(VisioEventListener o) { * @throws VisioException
DispatchEvents events = new DispatchEvents(this, o); */
if (events == null){ public void open(File f) throws VisioException {
System.out.println("You should never get null back when creating a DispatchEvents object"); try {
} ActiveXComponent documents = new ActiveXComponent(getProperty(
} "Documents").toDispatch());
Variant[] args = new Variant[1];
args[0] = new Variant(f.getPath());
documents.invoke("Open", args);
} catch (Exception e) {
e.printStackTrace();
throw new VisioException(e);
}
}
/**
* tells Visio to save the drawing
*
* @throws VisioException
*/
public void save() throws VisioException {
try {
ActiveXComponent document = new ActiveXComponent(getProperty(
"ActiveDocument").toDispatch());
document.invoke("Save");
} catch (Exception e) {
e.printStackTrace();
throw new VisioException(e);
}
}
public void open(File f) throws VisioException { /**
try { * terminates Visio
ActiveXComponent documents = new ActiveXComponent(getProperty("Documents").toDispatch()); */
Variant[] args = new Variant[1]; public void quit() {
args[0] = new Variant(f.getPath()); System.out.println("Received quit()");
documents.invoke("Open",args); // there can't be any open documents for this to work
} catch (Exception e) { // you'll get a visio error if you don't close them
e.printStackTrace(); ActiveXComponent document = new ActiveXComponent(getProperty(
throw new VisioException(e); "ActiveDocument").toDispatch());
} document.invoke("Close");
} invoke("Quit");
}
public void save() throws VisioException { /**
try { * runs the Visio export command
ActiveXComponent document = new ActiveXComponent(getProperty("ActiveDocument").toDispatch()); *
document.invoke("Save"); * @param f
} catch (Exception e) { * @throws VisioException
e.printStackTrace(); */
throw new VisioException(e); public void export(File f) throws VisioException {
} try {
} ActiveXComponent document = new ActiveXComponent(getProperty(
"ActivePage").toDispatch());
Variant[] args = new Variant[1];
args[0] = new Variant(f.getPath());
document.invoke("Export", args);
} catch (Exception e) {
throw new VisioException(e);
}
}
/** /**
* terminates visio * makes Visio visible so the user can watch
*/ *
public void quit() { * @param b
System.out.println("Received quit()"); * @throws VisioException
// there can't be any open documents for this to work */
// you'll get a visio error if you don't close them public void setVisible(boolean b) throws VisioException {
ActiveXComponent document = new ActiveXComponent(getProperty("ActiveDocument").toDispatch()); try {
document.invoke("Close"); setProperty("Visible", new Variant(b));
invoke("Quit"); } catch (Exception e) {
} throw new VisioException(e);
}
public void export(File f) throws VisioException { }
try {
ActiveXComponent document = new ActiveXComponent(getProperty("ActivePage").toDispatch());
Variant[] args = new Variant[1];
args[0] = new Variant(f.getPath());
document.invoke("Export",args);
} catch (Exception e) {
throw new VisioException(e);
}
}
public void setVisible(boolean b) throws VisioException {
try {
setProperty("Visible",new Variant(b));
} catch (Exception e) {
throw new VisioException(e);
}
}
} }

View File

@@ -1,120 +1,180 @@
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 static VisioAppFacade instance;
private VisioApp app; /** extension for image files */
private static VisioAppFacade instance; public static final String IMAGE_EXT = ".jpg";
/** extension for visio files */
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 String IMAGE_EXT = ".jpg"; /**
public static final String VISIO_EXT = ".vsd"; * Wrapper around Visio
public static final int BUFFER_SIZE = 2048; *
* @throws VisioException
private VisioAppFacade() throws VisioException { */
this.app = new VisioApp(); private VisioAppFacade() throws VisioException {
this.app = new VisioApp();
app.addEventListener(new VisioEventAdapter(app)); app.addEventListener(new VisioEventAdapter(app));
} }
public static VisioAppFacade getInstance() throws VisioException { /**
if (instance == null) { * @return the singleton instance of Visio
instance = new VisioAppFacade(); * @throws VisioException
} */
return instance; public static VisioAppFacade getInstance() throws VisioException {
} if (instance == null) {
instance = new VisioAppFacade();
}
return instance;
}
public byte[] createPreview(byte[] visioData) throws VisioException { /**
byte[] preview; * creates a preview in a temp file and returns the raw data.
File tmpFile; *
try { * @param visioData
tmpFile = getTempVisioFile(); * @return raw preview data
OutputStream out = new FileOutputStream(tmpFile); * @throws VisioException
out.write(visioData); */
out.close(); public byte[] createPreview(byte[] visioData) throws VisioException {
} catch (IOException ioe) { byte[] preview;
throw new VisioException(ioe); File tmpFile;
} try {
preview = createPreview(tmpFile); tmpFile = getTempVisioFile();
tmpFile.delete(); OutputStream out = new FileOutputStream(tmpFile);
return preview; out.write(visioData);
} out.close();
} catch (IOException ioe) {
throw new VisioException(ioe);
}
preview = createPreview(tmpFile);
tmpFile.delete();
return preview;
}
public byte[] createPreview(File visioFile) throws VisioException { /**
try { * reads a preview from a saved file
File imageFile; *
imageFile = getTempImageFile(); * @param visioFile
app.open(visioFile); * @return raw preview data
app.export(imageFile); * @throws VisioException
ByteArrayOutputStream bout = new ByteArrayOutputStream(); */
FileInputStream fin = new FileInputStream(imageFile); public byte[] createPreview(File visioFile) throws VisioException {
copy(fin, bout); try {
fin.close(); File imageFile;
imageFile.delete(); imageFile = getTempImageFile();
bout.close(); app.open(visioFile);
return bout.toByteArray(); app.export(imageFile);
} catch (IOException ioe) { ByteArrayOutputStream bout = new ByteArrayOutputStream();
throw new VisioException(ioe); FileInputStream fin = new FileInputStream(imageFile);
} copy(fin, bout);
} fin.close();
imageFile.delete();
bout.close();
return bout.toByteArray();
} catch (IOException ioe) {
throw new VisioException(ioe);
}
}
private void copy(InputStream in, OutputStream out) throws IOException { private void copy(InputStream in, OutputStream out) throws IOException {
byte[] buff = new byte[BUFFER_SIZE]; byte[] buff = new byte[BUFFER_SIZE];
int read; int read;
do { do {
read = in.read(buff); read = in.read(buff);
if (read > 0) { if (read > 0) {
out.write(buff,0,read); out.write(buff, 0, read);
} }
} while (read > 0); } while (read > 0);
} }
public byte[] createPreview(InputStream in) throws VisioException { /**
byte[] preview; * creates a preview from an input stream
//byte[] buff = new byte[2048]; *
//int read = 0; * @param in
OutputStream out; * @return byte contents of the preview stream
File tmpFile; * @throws VisioException
*/
public byte[] createPreview(InputStream in) throws VisioException {
byte[] preview;
// byte[] buff = new byte[2048];
// int read = 0;
OutputStream out;
File tmpFile;
try { try {
tmpFile = getTempVisioFile(); tmpFile = getTempVisioFile();
out = new FileOutputStream(tmpFile); out = new FileOutputStream(tmpFile);
copy(in, out); copy(in, out);
out.close(); out.close();
} catch (IOException ioe) { } catch (IOException ioe) {
throw new VisioException(ioe); throw new VisioException(ioe);
} }
preview = createPreview(tmpFile); preview = createPreview(tmpFile);
tmpFile.delete(); tmpFile.delete();
return preview; return preview;
} }
public void editDiagram(File f) throws VisioException { /**
app.open(f); * opens the file in Visio and makes the editor visible
app.setVisible(true); *
} * @param f
* the reference to the Visio file to be opened
* @throws VisioException
*/
public void editDiagram(File f) throws VisioException {
app.open(f);
app.setVisible(true);
}
private File getTempVisioFile() throws IOException { /**
return File.createTempFile("java",VISIO_EXT); * creates a temporary viso file
} *
* @return created visio temporary file
* @throws IOException
*/
private File getTempVisioFile() throws IOException {
return File.createTempFile("java", VISIO_EXT);
}
private File getTempImageFile() throws IOException { /**
return File.createTempFile("java",IMAGE_EXT); * creates a temporary image file and returns the File object
} *
* @return the created image file object
* @throws IOException
*/
private File getTempImageFile() throws IOException {
return File.createTempFile("java", IMAGE_EXT);
}
public void quit() { /** exit visio */
app.quit(); public void quit() {
instance = null; app.quit();
} instance = null;
}
} }

View File

@@ -1,177 +1,197 @@
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 {
/** /**
* Totally dummy value to make Eclipse quit complaining * Totally dummy value to make Eclipse quit complaining
*/ */
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
JButton chooseButton; JButton chooseButton;
JButton openButton; JButton openButton;
JPanel buttons; JPanel buttons;
ImageIcon theImage; ImageIcon theImage;
JLabel theLabel; // the icon on the page is actually this button's icon JLabel theLabel; // the icon on the page is actually this button's icon
File selectedFile; File selectedFile;
/** everyone should get this through getVisio() */ /** everyone should get this through getVisio() */
private VisioAppFacade visioProxy = null; private VisioAppFacade visioProxy = null;
// 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()) {
return true; return true;
} else { } else {
return (f.getName().toUpperCase().endsWith(".VSD")); return (f.getName().toUpperCase().endsWith(".VSD"));
} }
} }
public String getDescription() { public String getDescription() {
return "Visio Drawings"; return "Visio Drawings";
} }
} }
public VisioDemo() { public VisioDemo() {
super("Visio in Swing POC"); super("Visio in Swing POC");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
buttons = new JPanel(); buttons = new JPanel();
getContentPane().setLayout(new BorderLayout()); getContentPane().setLayout(new BorderLayout());
chooseButton = new JButton("Choose file to display"); chooseButton = new JButton("Choose file to display");
openButton = new JButton("Open file chosen file in Visio"); openButton = new JButton("Open file chosen file in Visio");
chooseButton.addActionListener(this); chooseButton.addActionListener(this);
openButton.addActionListener(this); openButton.addActionListener(this);
buttons.add(chooseButton); buttons.add(chooseButton);
buttons.add(openButton); buttons.add(openButton);
getContentPane().add(buttons, BorderLayout.SOUTH); getContentPane().add(buttons, BorderLayout.SOUTH);
theLabel = new JLabel(""); theLabel = new JLabel("");
getContentPane().add(theLabel, BorderLayout.CENTER); getContentPane().add(theLabel, BorderLayout.CENTER);
addWindowListener(this); addWindowListener(this);
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
setSize(640,480); setSize(640, 480);
this.setVisible(true); this.setVisible(true);
} }
public static void main(String args[]) throws Exception { public static void main(String args[]) throws Exception {
SwingUtilities.invokeLater(new Runnable(){ SwingUtilities.invokeLater(new Runnable() {
public void run(){ public void run() {
ComThread.InitSTA(); ComThread.InitSTA();
VisioDemo poc = new VisioDemo(); VisioDemo poc = new VisioDemo();
ComThread.Release(); ComThread.Release();
if (poc == null){ if (poc == null) {
System.out.println("poc== null? That should never happen!"); System.out.println("poc== null? That should never happen!");
} }
} }
}); });
} }
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
if (e.getSource() == chooseButton) { if (e.getSource() == chooseButton) {
pickFile(); pickFile();
} else if (e.getSource() == openButton) { } else if (e.getSource() == openButton) {
try { try {
openFile(); openFile();
} catch (Exception ex) { } catch (Exception ex) {
ex.printStackTrace(); ex.printStackTrace();
throw new RuntimeException(ex); throw new RuntimeException(ex);
} }
} else { } else {
System.out.println("Awesome!"); System.out.println("Awesome!");
} }
} }
private void pickFile() { private void pickFile() {
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
chooser.setFileFilter(new VisioFileFilter()); .setCurrentDirectory(new File(System
int returnVal = chooser.showOpenDialog(this); .getProperty("user.dir")));
if(returnVal == JFileChooser.APPROVE_OPTION) { chooser.setFileFilter(new VisioFileFilter());
selectedFile = chooser.getSelectedFile(); int returnVal = chooser.showOpenDialog(this);
showSelectedFilePreview(); if (returnVal == JFileChooser.APPROVE_OPTION) {
} selectedFile = chooser.getSelectedFile();
} catch (Exception e) { showSelectedFilePreview();
e.printStackTrace(); }
} } catch (Exception e) {
} e.printStackTrace();
}
}
/** /**
* 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)
* @return * rather than root thread
*/ *
private VisioAppFacade getVisio(){ * @return
if (visioProxy == null){ */
try { private VisioAppFacade getVisio() {
visioProxy = VisioAppFacade.getInstance(); if (visioProxy == null) {
} catch (VisioException ve){ try {
System.out.println("ailed to openFile()"); visioProxy = VisioAppFacade.getInstance();
ve.printStackTrace(); } catch (VisioException ve) {
} System.out.println("ailed to openFile()");
} ve.printStackTrace();
return visioProxy; }
} }
private void showSelectedFilePreview() throws VisioException { return visioProxy;
if (selectedFile != null) { }
byte[] image = getVisio().createPreview(selectedFile);
theImage = new ImageIcon(image);
theLabel.setIcon(theImage);
}
}
private void openFile() throws VisioException { private void showSelectedFilePreview() throws VisioException {
try { if (selectedFile != null) {
getVisio().editDiagram(selectedFile); byte[] image = getVisio().createPreview(selectedFile);
showSelectedFilePreview(); theImage = new ImageIcon(image);
} catch (VisioException ve){ theLabel.setIcon(theImage);
System.out.println("ailed to openFile()"); }
ve.printStackTrace(); }
}
} private void openFile() throws VisioException {
try {
getVisio().editDiagram(selectedFile);
showSelectedFilePreview();
} catch (VisioException ve) {
System.out.println("ailed to openFile()");
ve.printStackTrace();
}
public void windowActivated(WindowEvent e) { }
}
public void windowClosed(WindowEvent e) { public void windowActivated(WindowEvent e) {
System.out.println("WINDOW CLOSED"); }
if (visioProxy != null){
visioProxy.quit();
}
}
public void windowClosing(WindowEvent e){
}
public void windowDeactivated(WindowEvent e){ public void windowClosed(WindowEvent e) {
} System.out.println("WINDOW CLOSED");
if (visioProxy != null) {
visioProxy.quit();
}
}
public void windowDeiconified(WindowEvent e){ public void windowClosing(WindowEvent e) {
} }
public void windowIconified(WindowEvent e){ public void windowDeactivated(WindowEvent e) {
System.out.println("Fooboo"); }
}
public void windowOpened(WindowEvent e){ public void windowDeiconified(WindowEvent e) {
} }
public void windowIconified(WindowEvent e) {
System.out.println("Fooboo");
}
public void windowOpened(WindowEvent e) {
}
} }

View File

@@ -1,59 +1,68 @@
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 {
VisioApp app = null; VisioApp app = null;
public VisioEventAdapter(VisioApp pApp){ public VisioEventAdapter(VisioApp pApp) {
app = pApp; app = pApp;
System.out.println("Event listener constructed"); System.out.println("Event listener constructed");
} }
public void BeforeQuit(Variant[] args){ }
public void DocumentChanged(Variant[] args){ public void BeforeQuit(Variant[] args) {
System.out.println("documentChanged()"); }
}
public void DocumentCloseCanceled(Variant[] args){ } public void DocumentChanged(Variant[] args) {
System.out.println("documentChanged()");
}
public void DocumentCreated(Variant[] args){ } public void DocumentCloseCanceled(Variant[] args) {
}
public void DocumentOpened(Variant[] args){ public void DocumentCreated(Variant[] args) {
System.out.println("DocumentOpened()"); }
}
public void DocumentSaved(Variant[] args){ } public void DocumentOpened(Variant[] args) {
System.out.println("DocumentOpened()");
}
public void DocumentSavedAs(Variant[] args){ } public void DocumentSaved(Variant[] args) {
}
public Variant QueryCancelDocumentClose(Variant[] args){ public void DocumentSavedAs(Variant[] args) {
System.out.println("QueryCancelDocumentClose()"); }
return new Variant(false);
} public Variant QueryCancelDocumentClose(Variant[] args) {
System.out.println("QueryCancelDocumentClose()");
/** return new Variant(false);
* we don't actually let it quit. We block it so }
* that we don't have to relaunch when we look at a new document
*/ /**
public Variant QueryCancelQuit(Variant[] args) { * we don't actually let it quit. We block it so that we don't have to
// these may throw VisioException * relaunch when we look at a new document
System.out.println("Saving document, hiding and telling visio not to quit"); */
try { public Variant QueryCancelQuit(Variant[] args) {
app.save(); // these may throw VisioException
app.setVisible(false); System.out
} catch (VisioException ve){ .println("Saving document, hiding and telling visio not to quit");
System.out.println("ailed to openFile()"); try {
ve.printStackTrace(); app.save();
} app.setVisible(false);
return new Variant(true); } catch (VisioException ve) {
} System.out.println("ailed to openFile()");
ve.printStackTrace();
}
return new Variant(true);
}
} }

View File

@@ -1,33 +1,33 @@
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 {
public void BeforeQuit(Variant[] args); public void BeforeQuit(Variant[] args);
public void DocumentChanged(Variant[] args); public void DocumentChanged(Variant[] args);
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);
public void DocumentSaved(Variant[] args); public void DocumentSaved(Variant[] args);
public void DocumentSavedAs(Variant[] args); public void DocumentSavedAs(Variant[] args);
public Variant QueryCancelQuit(Variant[] args); public Variant QueryCancelQuit(Variant[] args);
} }

View File

@@ -1,22 +1,25 @@
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 {
/** /**
* Totally dummy value to make Eclipse quit complaining * Totally dummy value to make Eclipse quit complaining
*/ */
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public VisioException(String msg) { public VisioException(String msg) {
super(msg); super(msg);
} }
public VisioException(Throwable cause) { public VisioException(Throwable cause) {
super(cause); super(cause);
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -26,67 +26,78 @@ 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.
*
* *
*
*/ */
public class ActiveXDispatchEvents extends DispatchEvents { 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
public ActiveXDispatchEvents(Dispatch sourceOfEvent, Object eventSink) { * @param eventSink
super(sourceOfEvent, eventSink, null ); * Java object that wants to receive the events
} */
public ActiveXDispatchEvents(Dispatch sourceOfEvent, Object eventSink) {
super(sourceOfEvent, eventSink, null);
}
/** /**
* 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
public ActiveXDispatchEvents(Dispatch sourceOfEvent, Object eventSink, String progId) { * Java object that wants to receive the events
super(sourceOfEvent, eventSink, progId, null ); * @param progId
} * ???
*/
public ActiveXDispatchEvents(Dispatch sourceOfEvent, Object eventSink,
String progId) {
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> *
* >ActiveXDispatchEvents de = * <pre>
* new ActiveXDispatchEvents(someDispatch,someEventHAndler, * &gt;ActiveXDispatchEvents de =
* "Excel.Application", * new ActiveXDispatchEvents(someDispatch,someEventHAndler,
* "C:\\Program Files\\Microsoft Office\\OFFICE11\\EXCEL.EXE"); * &quot;Excel.Application&quot;,
* * &quot;C:\\Program Files\\Microsoft Office\\OFFICE11\\EXCEL.EXE&quot;);
* @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 progId , mandatory if the typelib is specified * @param eventSink Java object that wants to receive the events
* @param typeLib The location of the typelib to use * @param progId , mandatory if the typelib is specified
*/ * @param typeLib The location of the typelib to use
public ActiveXDispatchEvents(Dispatch sourceOfEvent, Object eventSink, String progId, String typeLib) *
{ */
super(sourceOfEvent, eventSink, progId, typeLib); public ActiveXDispatchEvents(Dispatch sourceOfEvent, Object eventSink,
} String progId, String 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) {
InvocationProxy newProxy = new ActiveXInvocationProxy(); InvocationProxy newProxy = new ActiveXInvocationProxy();
newProxy.setTarget(pTargetObject); newProxy.setTarget(pTargetObject);
return newProxy; return newProxy;

View File

@@ -29,63 +29,70 @@ 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,
if (targetMethod != null){ parametersAsJavaClasses);
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)) {
mVariantToBeReturned = new Variant(mReturnedByInvocation); mVariantToBeReturned = new Variant(mReturnedByInvocation);
} else { } else {
mVariantToBeReturned = (Variant) mReturnedByInvocation; mVariantToBeReturned = (Variant) mReturnedByInvocation;
@@ -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
@@ -109,23 +118,27 @@ public class ActiveXInvocationProxy extends InvocationProxy {
e.printStackTrace(); e.printStackTrace();
} }
return mVariantToBeReturned; return mVariantToBeReturned;
} }
/** /**
* 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];
for ( int parameterIndex = 0 ; parameterIndex < numParameters; parameterIndex++){ for (int parameterIndex = 0; parameterIndex < numParameters; parameterIndex++) {
Object oneParameterObject = parametersAsJavaObjects[parameterIndex]; Object oneParameterObject = parametersAsJavaObjects[parameterIndex];
if (oneParameterObject == null){ if (oneParameterObject == null) {
parametersAsJavaClasses[parameterIndex] = null; parametersAsJavaClasses[parameterIndex] = null;
} else { } else {
Class oneParameterClass = oneParameterObject.getClass(); Class oneParameterClass = oneParameterObject.getClass();
@@ -137,31 +150,34 @@ 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];
for ( int parameterIndex = 0 ; parameterIndex < numParameters; parameterIndex++){ for (int parameterIndex = 0; parameterIndex < numParameters; parameterIndex++) {
Variant oneParameterObject = targetParameters[parameterIndex]; Variant oneParameterObject = targetParameters[parameterIndex];
if (oneParameterObject == null){ if (oneParameterObject == null) {
parametersAsJavaObjects[parameterIndex] = null; parametersAsJavaObjects[parameterIndex] = null;
} else { } else {
try { try {
parametersAsJavaObjects[parameterIndex] = oneParameterObject.toJavaObject(); parametersAsJavaObjects[parameterIndex] = oneParameterObject
} catch (NotImplementedException nie){ .toJavaObject();
throw new IllegalArgumentException("Can't convert parameter "+parameterIndex+ } catch (NotImplementedException nie) {
" type "+oneParameterObject.getvt() throw new IllegalArgumentException(
+" to java object: "+nie.getMessage()); "Can't convert parameter " + parameterIndex
+ " type " + oneParameterObject.getvt()
+ " to java object: " + nie.getMessage());
} }
} }
} }
return parametersAsJavaObjects; return parametersAsJavaObjects;
} }
} }

View File

@@ -22,111 +22,120 @@ 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
* that was returned by the underlying com code
**/
protected int hr;
/** No documentation is available at this time. Someone should document this field */
protected int m_helpContext;
/** No documentation is available at this time. Someone should document this field */
protected String m_helpFile;
/** No documentation is available at this time. Someone should document this field */
protected String m_source;
/** /**
* constructor * COM code initializes this filed with an appropriate return code that was
* * returned by the underlying com code
*/ */
public ComException() { protected int hr;
super(); /**
} * No documentation is available at this time. Someone should document this
* field
*/
protected int m_helpContext;
/**
* No documentation is available at this time. Someone should document this
* field
*/
protected String m_helpFile;
/**
* No documentation is available at this time. Someone should document this
* field
*/
protected String m_source;
/** /**
* constructor with error code? * constructor
* *
* @param newHr ?? */
*/ public ComException() {
public ComException(int newHr) { super();
super(); }
this.hr = newHr;
}
/** /**
* @param newHr * constructor with error code?
* @param description *
*/ * @param newHr ??
public ComException(int newHr, String description) { */
super(description); public ComException(int newHr) {
this.hr = newHr; super();
} this.hr = newHr;
}
/** /**
* @param newHr * @param newHr
* @param source * @param description
* @param helpFile */
* @param helpContext public ComException(int newHr, String description) {
*/ super(description);
public ComException(int newHr, String source, String helpFile, this.hr = newHr;
int helpContext) { }
super();
this.hr = newHr;
m_source = source;
m_helpFile = helpFile;
m_helpContext = helpContext;
}
/** /**
* @param newHr * @param newHr
* @param description * @param source
* @param source * @param helpFile
* @param helpFile * @param helpContext
* @param helpContext */
*/ public ComException(int newHr, String source, String helpFile,
public ComException(int newHr, String description, String source, int helpContext) {
String helpFile, int helpContext) { super();
super(description); this.hr = newHr;
this.hr = newHr; m_source = source;
m_source = source; m_helpFile = helpFile;
m_helpFile = helpFile; m_helpContext = helpContext;
m_helpContext = helpContext; }
}
/** /**
* @param description * @param newHr
*/ * @param description
public ComException(String description) { * @param source
super(description); * @param helpFile
} * @param helpContext
*/
public ComException(int newHr, String description, String source,
String helpFile, int helpContext) {
super(description);
this.hr = newHr;
m_source = source;
m_helpFile = helpFile;
m_helpContext = helpContext;
}
/** /**
* @return int representation of the help context * @param description
*/ */
// Methods public ComException(String description) {
public int getHelpContext() { super(description);
return m_helpContext; }
}
/** /**
* @return String ??? help file * @return int representation of the help context
*/ */
public String getHelpFile() { // Methods
return m_helpFile; public int getHelpContext() {
} return m_helpContext;
}
/** /**
* @return int hr result ?? * @return String ??? help file
*/ */
public int getHResult() { public String getHelpFile() {
return hr; return m_helpFile;
} }
/** /**
* @return String source ?? * @return int hr result ??
*/ */
public String getSource() { public int getHResult() {
return m_source; return hr;
} }
/**
* @return String source ??
*/
public String getSource() {
return m_source;
}
} }

View File

@@ -23,63 +23,66 @@ package com.jacob.com;
* COM Fail Exception class raised when there is a problem * COM Fail Exception class raised when there is a problem
*/ */
public class ComFailException extends ComException { public class ComFailException extends ComException {
/** /**
* eclipse generated to get rid of a wanring * eclipse generated to get rid of a wanring
*/ */
private static final long serialVersionUID = -266047261992987700L; private static final long serialVersionUID = -266047261992987700L;
/** /**
* Constructor * Constructor
* @param hrNew *
*/ * @param hrNew
public ComFailException(int hrNew) { */
super(hrNew); public ComFailException(int hrNew) {
} super(hrNew);
}
/** /**
* Constructor * Constructor
* @param hrNew *
* @param message * @param hrNew
*/ * @param message
public ComFailException(int hrNew, String message) { */
super(hrNew, message); public ComFailException(int hrNew, String message) {
} super(hrNew, message);
}
/** /**
* @param hrNew * @param hrNew
* @param source * @param source
* @param helpFile * @param helpFile
* @param helpContext * @param helpContext
*/ */
public ComFailException(int hrNew, String source, String helpFile, public ComFailException(int hrNew, String source, String helpFile,
int helpContext) { int helpContext) {
super(hrNew, source, helpFile, helpContext); super(hrNew, source, helpFile, helpContext);
} }
/** /**
* Constructor * Constructor
* @param hrNew *
* @param description * @param hrNew
* @param source * @param description
* @param helpFile * @param source
* @param helpContext * @param helpFile
*/ * @param helpContext
public ComFailException(int hrNew, String description, String source, */
String helpFile, int helpContext) { public ComFailException(int hrNew, String description, String source,
super(hrNew, description, source, helpFile, helpContext); String helpFile, int helpContext) {
} super(hrNew, description, source, helpFile, helpContext);
}
/** /**
* No argument Constructor * No argument Constructor
*/ */
public ComFailException() { public ComFailException() {
super(); super();
} }
/** /**
* @param message * @param message
*/ */
public ComFailException(String message) { public ComFailException(String message) {
super(message); super(message);
} }
} }

View File

@@ -20,135 +20,150 @@
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;
private static final int STA = 0x2; private static final int STA = 0x2;
/** /**
* Comment for <code>haveSTA</code> * Comment for <code>haveSTA</code>
*/ */
public static boolean haveSTA = false; public static boolean haveSTA = false;
/** /**
* Comment for <code>mainSTA</code> * Comment for <code>mainSTA</code>
*/ */
public static MainSTA mainSTA = null; public static MainSTA mainSTA = null;
/** /**
* 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 * Apartment
*/ */
public static synchronized void InitMTA() { public static synchronized void InitMTA() {
InitMTA(false); InitMTA(false);
} }
/** /**
* Initialize the current java thread to be an STA * Initialize the current java thread to be an STA
*/ */
public static synchronized void InitSTA() { public static synchronized void InitSTA() {
InitSTA(false); InitSTA(false);
} }
/** /**
* 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) { */
Init(createMainSTA, MTA); public static synchronized void InitMTA(boolean createMainSTA) {
} Init(createMainSTA, MTA);
}
/** /**
* 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) { */
Init(createMainSTA, STA); public static synchronized void InitSTA(boolean createMainSTA) {
} Init(createMainSTA, STA);
}
/** /**
* *
*/ */
public static synchronized void startMainSTA() { public static synchronized void startMainSTA() {
mainSTA = new MainSTA(); mainSTA = new MainSTA();
haveSTA = true; haveSTA = true;
} }
/** /**
* *
*/ */
public static synchronized void quitMainSTA() { public static synchronized void quitMainSTA() {
if (mainSTA != null) if (mainSTA != null)
mainSTA.quit(); mainSTA.quit();
} }
/** /**
* 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 mode * @param createMainSTA
*/ * @param mode
public static synchronized void Init(boolean createMainSTA, int mode) { */
if (createMainSTA && !haveSTA) { public static synchronized void Init(boolean createMainSTA, int mode) {
// if the current thread is going to be in the MTA and there if (createMainSTA && !haveSTA) {
// is no STA thread yet, then create a main STA thread // if the current thread is going to be in the MTA and there
// to avoid COM creating its own // is no STA thread yet, then create a main STA thread
startMainSTA(); // to avoid COM creating its own
} startMainSTA();
if (JacobObject.isDebugEnabled()){JacobObject.debug("ComThread: before Init: "+mode);} }
doCoInitialize(mode); if (JacobObject.isDebugEnabled()) {
if (JacobObject.isDebugEnabled()){JacobObject.debug("ComThread: after Init: "+mode);} JacobObject.debug("ComThread: before Init: " + mode);
ROT.addThread(); }
if (JacobObject.isDebugEnabled()){JacobObject.debug("ComThread: after ROT.addThread: "+mode); } doCoInitialize(mode);
} if (JacobObject.isDebugEnabled()) {
JacobObject.debug("ComThread: after Init: " + mode);
}
ROT.addThread();
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()) {
ROT.clearObjects(); JacobObject.debug("ComThread: before clearObjects");
if (JacobObject.isDebugEnabled()){JacobObject.debug("ComThread: before UnInit"); } }
doCoUninitialize(); ROT.clearObjects();
if (JacobObject.isDebugEnabled()){JacobObject.debug("ComThread: after UnInit"); } if (JacobObject.isDebugEnabled()) {
} JacobObject.debug("ComThread: before UnInit");
}
/** doCoUninitialize();
* @deprecated the java model leave the responsibility of clearing up objects if (JacobObject.isDebugEnabled()) {
* to the Garbage Collector. Our programming model should not require that the JacobObject.debug("ComThread: after UnInit");
* user specifically remove object from the thread. }
* }
* This will remove an object from the ROT
* @param o
*/
public static synchronized void RemoveObject(JacobObject o)
{
ROT.removeObject(o);
}
/** /**
* @param threadModel * @deprecated the java model leave the responsibility of clearing up
*/ * objects to the Garbage Collector. Our programming model
public static native void doCoInitialize(int threadModel); * should not require that the user specifically remove object
* from the thread.
*
* This will remove an object from the ROT
* @param o
*/
@Deprecated
public static synchronized void RemoveObject(JacobObject o) {
ROT.removeObject(o);
}
/** /**
* * @param threadModel
*/ */
public static native void doCoUninitialize(); public static native void doCoInitialize(int threadModel);
/** /**
* load the Jacob DLL. We do this in case COMThread is called before *
* any other reference to one of the JacboObject subclasses is made. */
*/ public static native void doCoUninitialize();
static {
LibraryLoader.loadJacobLibrary(); /**
} * load the Jacob DLL. We do this in case COMThread is called before any
* other reference to one of the JacboObject subclasses is made.
*/
static {
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,29 +24,30 @@ import java.util.Date;
/** /**
* java / windows date conversion utilities * java / windows date conversion utilities
*
* @author joe * @author joe
* *
*/ */
public class DateUtilities { 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
*/ */
static public Date convertWindowsTimeToDate(double comTime){ static public Date convertWindowsTimeToDate(double comTime) {
return new Date(convertWindowsTimeToMilliseconds (comTime)); return new Date(convertWindowsTimeToMilliseconds(comTime));
} }
/** /**
* 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,19 +69,20 @@ 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());
} }
/** /**
* Convert a Java time to a COM time. * Convert a Java time to a COM time.
* *
@@ -99,5 +101,5 @@ public class DateUtilities {
result = (milliseconds / 86400000D) + 25569D; result = (milliseconds / 86400000D) + 25569D;
return result; return result;
}//convertMillisecondsToWindowsTime() }// convertMillisecondsToWindowsTime()
} }

File diff suppressed because it is too large Load Diff

View File

@@ -20,177 +20,200 @@
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.
* The COM layer knows the name of this variable and puts the windows
* memory pointer here.
*/
int m_pConnPtProxy = 0;
/**
* the wrapper for the event sink.
* This object is the one that will be sent a message when an event
* occurs in the MS layer. Normally, the InvocationProxy will forward
* the messages to a wrapped object that it contains.
*/
InvocationProxy mInvocationProxy = null;
/** /**
* This is the most commonly used constructor. * pointer to an MS data struct. The COM layer knows the name of this
* <p> * variable and puts the windows memory pointer here.
* Creates the event callback linkage between the the */
* MS program represented by the Dispatch object and the int m_pConnPtProxy = 0;
* Java object that will receive the callback.
* <p>
* Can be used on any object that implements IProvideClassInfo.
*
* @param sourceOfEvent 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) {
this(sourceOfEvent, eventSink, null );
}
/** /**
* None of the samples use this constructor. * the wrapper for the event sink. This object is the one that will be sent
* <p> * a message when an event occurs in the MS layer. Normally, the
* Creates the event callback linkage between the the * InvocationProxy will forward the messages to a wrapped object that it
* MS program represented by the Dispatch object and the * contains.
* Java object that will receive the callback. */
* <p> InvocationProxy mInvocationProxy = null;
* Used when the program doesn't implement IProvideClassInfo. It provides
* a way to find the TypeLib in the registry based on the programId. The TypeLib
* is looked up in the registry on the path
* HKEY_LOCAL_MACHINE/SOFTWARE/Classes/CLSID/(CLID drived from progid)/ProgID/Typelib
*
* @param sourceOfEvent Dispatch object who's MS app will generate callbacks
* @param eventSink 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) {
this(sourceOfEvent, eventSink, progId, null );
}
/** /**
* Creates the event callback linkage between the the * This is the most commonly used constructor.
* MS program represented by the Dispatch object and the * <p>
* Java object that will receive the callback. * Creates the event callback linkage between the the MS program represented
* <p> * by the Dispatch object and the Java object that will receive the
* This method was added because Excel doesn't implement IProvideClassInfo * callback.
* and the registry entry for Excel.Application doesn't include a typelib key. * <p>
* * Can be used on any object that implements IProvideClassInfo.
* <pre> *
* DispatchEvents de = * @param sourceOfEvent
* new DispatchEvents(someDispatch,someEventHAndler, * Dispatch object who's MS app will generate callbacks
* "Excel.Application", * @param eventSink
* "C:\\Program Files\\Microsoft Office\\OFFICE11\\EXCEL.EXE"); * Java object that wants to receive the events
* </pre> */
* @param sourceOfEvent Dispatch object who's MS app will generate callbacks public DispatchEvents(Dispatch sourceOfEvent, Object eventSink) {
* @param eventSink Java object that wants to receive the events this(sourceOfEvent, eventSink, null);
* @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) * None of the samples use this constructor.
{ * <p>
if (JacobObject.isDebugEnabled()){ * Creates the event callback linkage between the the MS program represented
System.out.println( * by the Dispatch object and the Java object that will receive the
"DispatchEvents: Registering "+ eventSink + "for events "); * callback.
* <p>
* Used when the program doesn't implement IProvideClassInfo. It provides a
* way to find the TypeLib in the registry based on the programId. The
* TypeLib is looked up in the registry on the path
* HKEY_LOCAL_MACHINE/SOFTWARE/Classes/CLSID/(CLID drived from
* progid)/ProgID/Typelib
*
* @param sourceOfEvent
* Dispatch object who's MS app will generate callbacks
* @param eventSink
* 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) {
this(sourceOfEvent, eventSink, progId, null);
}
/**
* Creates the event callback linkage between the the MS program represented
* by the Dispatch object and the Java object that will receive the
* callback.
* <p>
* This method was added because Excel doesn't implement IProvideClassInfo
* and the registry entry for Excel.Application doesn't include a typelib
* key.
*
* <pre>
* DispatchEvents de = new DispatchEvents(someDispatch, someEventHAndler,
* &quot;Excel.Application&quot;,
* &quot;C:\\Program Files\\Microsoft Office\\OFFICE11\\EXCEL.EXE&quot;);
* </pre>
*
* @param sourceOfEvent
* Dispatch object who's MS app will generate callbacks
* @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) {
if (JacobObject.isDebugEnabled()) {
System.out.println("DispatchEvents: Registering " + eventSink
+ "for events ");
} }
if (eventSink instanceof InvocationProxy) { if (eventSink instanceof InvocationProxy) {
mInvocationProxy = (InvocationProxy) eventSink; mInvocationProxy = (InvocationProxy) eventSink;
} else { } else {
mInvocationProxy = getInvocationProxy(eventSink); mInvocationProxy = getInvocationProxy(eventSink);
} }
if (mInvocationProxy != null) { if (mInvocationProxy != null) {
init3(sourceOfEvent, mInvocationProxy, progId, typeLib); init3(sourceOfEvent, mInvocationProxy, progId, typeLib);
} else { } else {
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
* @param pTargetObject * target
* @return InvocationProxy an instance of the proxy this DispatchEvents will send to the COM layer *
*/ * @param pTargetObject
protected InvocationProxy getInvocationProxy(Object pTargetObject){ * @return InvocationProxy an instance of the proxy this DispatchEvents will
* send to the COM layer
*/
protected InvocationProxy getInvocationProxy(Object pTargetObject) {
InvocationProxy newProxy = new InvocationProxyAllVariants(); InvocationProxy newProxy = new InvocationProxyAllVariants();
newProxy.setTarget(pTargetObject); newProxy.setTarget(pTargetObject);
return newProxy; return newProxy;
} }
/** /**
* 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
* @param src dispatch that is the source of the messages * dispatch that is the source of the messages
* @param sink the object that will receive the messages * @param sink
* @param progId optional program id. most folks don't need this either * the object that will receive the messages
* @param typeLib optional parameter for those programs that don't register their type libs (like Excel) * @param progId
*/ * optional program id. most folks don't need this either
private native void init3(Dispatch src, Object sink, String progId, String typeLib); * @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);
/** /**
* 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() { */
safeRelease(); protected void finalize() {
} safeRelease();
}
/*
* (non-Javadoc) /*
* @see com.jacob.com.JacobObject#safeRelease() * (non-Javadoc)
*/ *
public void safeRelease(){ * @see com.jacob.com.JacobObject#safeRelease()
if (mInvocationProxy!=null){ */
mInvocationProxy.setTarget(null); public void safeRelease() {
} if (mInvocationProxy != null) {
mInvocationProxy = null; mInvocationProxy.setTarget(null);
super.safeRelease(); }
if (m_pConnPtProxy != 0){ mInvocationProxy = null;
release(); super.safeRelease();
m_pConnPtProxy = 0; if (m_pConnPtProxy != 0) {
} else { release();
// looks like a double release m_pConnPtProxy = 0;
if (isDebugEnabled()){debug("DispatchEvents:"+this.hashCode()+" double release");} } else {
} // looks like a 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

@@ -29,58 +29,64 @@ package com.jacob.com;
* construct a separate DispatchProxy instance for each such case! * construct a separate DispatchProxy instance for each such case!
*/ */
public class DispatchProxy extends JacobObject { public class DispatchProxy extends JacobObject {
/** /**
* Comment for <code>m_pStream</code> * Comment for <code>m_pStream</code>
*/ */
public int m_pStream; public int m_pStream;
/** /**
* Marshals the passed in dispatch into the stream * Marshals the passed in dispatch into the stream
* @param localDispatch *
*/ * @param localDispatch
public DispatchProxy(Dispatch localDispatch) { */
MarshalIntoStream(localDispatch); public DispatchProxy(Dispatch localDispatch) {
} MarshalIntoStream(localDispatch);
}
/** /**
* *
* @return Dispatch the dispatch retrieved from the stream * @return Dispatch the dispatch retrieved from the stream
*/ */
public Dispatch toDispatch() { public Dispatch toDispatch() {
return MarshalFromStream(); return MarshalFromStream();
} }
private native void MarshalIntoStream(Dispatch d); private native void MarshalIntoStream(Dispatch d);
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) /*
* @see java.lang.Object#finalize() * (non-Javadoc)
*/ *
public void finalize() { * @see java.lang.Object#finalize()
safeRelease(); */
} public void finalize() {
safeRelease();
/* }
* (non-Javadoc)
* @see com.jacob.com.JacobObject#safeRelease() /*
*/ * (non-Javadoc)
public void safeRelease() *
{ * @see com.jacob.com.JacobObject#safeRelease()
super.safeRelease(); */
if (m_pStream != 0){ public void safeRelease() {
release(); super.safeRelease();
m_pStream = 0; if (m_pStream != 0) {
} else { release();
// looks like a double release m_pStream = 0;
if (isDebugEnabled()){debug(this.getClass().getName()+":"+this.hashCode()+" double release");} } else {
} // looks like a double release
} if (isDebugEnabled()) {
debug(this.getClass().getName() + ":" + this.hashCode()
+ " double release");
}
}
}
} }

View File

@@ -23,121 +23,134 @@ 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
private int m_pIEnumVARIANT; java.util.Enumeration<Variant> {
private int m_pIEnumVARIANT;
private final Variant[] m_recBuf = new Variant[1]; private final Variant[] m_recBuf = new Variant[1];
// this only gets called from JNI // this only gets called from JNI
// //
protected EnumVariant(int pIEnumVARIANT) { protected EnumVariant(int pIEnumVARIANT) {
m_pIEnumVARIANT = pIEnumVARIANT; m_pIEnumVARIANT = pIEnumVARIANT;
} }
/** /**
* @param disp * @param disp
*/ */
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, if (evv.getvt() != Variant.VariantObject)
new Variant[0], hres); //
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 throw new ComFailException("Can't obtain EnumVARIANT");
//
throw new ComFailException("Can't obtain EnumVARIANT");
EnumVariant tmp = evv.toEnumVariant(); EnumVariant tmp = evv.toEnumVariant();
m_pIEnumVARIANT = tmp.m_pIEnumVARIANT; m_pIEnumVARIANT = tmp.m_pIEnumVARIANT;
tmp.m_pIEnumVARIANT = 0; tmp.m_pIEnumVARIANT = 0;
} }
/** /**
* 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() {
if (m_recBuf[0] == null) { {
if (this.Next(m_recBuf) <= 0) if (m_recBuf[0] == null) {
return false; if (this.Next(m_recBuf) <= 0)
} return false;
return true; }
} return true;
} }
}
/** /**
* Implements java.util.Enumeration * Implements java.util.Enumeration
* @return next element in the enumeration *
*/ * @return next element in the enumeration
public Object nextElement() { */
Object last = m_recBuf[0]; public Variant nextElement() {
if (last == null) { Variant last = m_recBuf[0];
if (this.Next(m_recBuf) <= 0) if (last == null) {
throw new java.util.NoSuchElementException(); if (this.Next(m_recBuf) <= 0)
last = m_recBuf[0]; throw new java.util.NoSuchElementException();
} last = m_recBuf[0];
m_recBuf[0] = null; }
return last; m_recBuf[0] = null;
} return last;
}
/** /**
* 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
public Variant Next() { * @deprecated use nextElement() instead
if (hasMoreElements()) */
return (Variant) nextElement(); @Deprecated
return null; public Variant Next() {
} if (hasMoreElements())
return nextElement();
return null;
}
/** /**
* @param receiverArray * This should be private and wrapped to protect JNI layer.
* @return don't know what the int is that is returned, help! *
*/ * @param receiverArray
public native int Next(Variant[] receiverArray); * @return Returns the next variant object pointer as an int from windows
* layer
*/
public native int Next(Variant[] receiverArray);
/** /**
* @param count * This should be private and wrapped to protect JNI layer.
*/ *
public native void Skip(int count); * @param count
* number to skip
*/
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,20 +23,19 @@ 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 {
@@ -44,58 +43,66 @@ public abstract class InvocationProxy {
* the object we will try and forward to. * the object we will try and forward to.
*/ */
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 name is calculated by the underlying JNI code from the MS windows
* Callback function name. The method is assumed to take an array of Variant
* objects. The method may return a Variant or be a void. Those are the only
* two options that will not blow up.
* <p>
* Subclasses that override this should make sure mTargetObject is not null before processing.
*
* @param methodName name of method in mTargetObject we will invoke
* @param targetParameters Variant[] that is the single parameter to the method
*/
public abstract Variant invoke(String methodName, Variant targetParameters[]);
/**
* used by EventProxy.cpp to create variant objects in the right thread
* @return Variant object that will be used by the COM layer
*/
public Variant getVariant(){
return new VariantViaEvent();
}
/** /**
* Sets the target for this InvocationProxy. * The method actually invoked by EventProxy.cpp. The method name is
* @param pTargetObject * calculated by the underlying JNI code from the MS windows Callback
* @throws IllegalArgumentException if target is not publicly accessable * function name. The method is assumed to take an array of Variant objects.
*/ * The method may return a Variant or be a void. Those are the only two
public void setTarget(Object pTargetObject){ * options that will not blow up.
if (JacobObject.isDebugEnabled()){ * <p>
JacobObject.debug( * Subclasses that override this should make sure mTargetObject is not null
"InvocationProxy: setting target "+pTargetObject); * before processing.
*
* @param methodName
* 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[]);
/**
* used by EventProxy.cpp to create variant objects in the right thread
*
* @return Variant object that will be used by the COM layer
*/
public Variant getVariant() {
return new VariantViaEvent();
}
/**
* Sets the target for this InvocationProxy.
*
* @param pTargetObject
* @throws IllegalArgumentException
* if target is not publicly accessible
*/
public void setTarget(Object pTargetObject) {
if (JacobObject.isDebugEnabled()) {
JacobObject.debug("InvocationProxy: setting target "
+ 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");
} }
} }
mTargetObject = pTargetObject; mTargetObject = pTargetObject;
} }
} }

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,20 +95,22 @@ 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
if (JacobObject.isDebugEnabled()){ // methods
JacobObject.debug("InvocationProxy: listener ("+mTargetObject+") doesn't implement " if (JacobObject.isDebugEnabled()) {
+ methodName); JacobObject.debug("InvocationProxy: listener (" + mTargetObject
+ ") doesn't implement " + methodName);
} }
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
e.printStackTrace(); e.printStackTrace();
// 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
throw e; throw e;
} 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
+ methodName); .debug("InvocationProxy: probably tried to access public method on non public class"
+ methodName);
} }
e.printStackTrace(); e.printStackTrace();
} catch (InvocationTargetException e) { } catch (InvocationTargetException e) {
@@ -109,6 +118,6 @@ public class InvocationProxyAllVariants extends InvocationProxy {
e.printStackTrace(); e.printStackTrace();
} }
return mVariantToBeReturned; return mVariantToBeReturned;
} }
} }

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,18 +32,18 @@ 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");
} }
/** /**
* standard constructor * standard constructor
*
* @param message * @param message
*/ */
public JacobException(String message){ public JacobException(String message) {
super(message); super(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,116 +35,77 @@ 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 = ""; public JacobObject() {
ROT.addObject(this);
}
/** /**
* holds the build date as retrieved from the version.properties * Finalizers call this method. This method should release any COM data
* file that exists in the JAR * structures in a way that it can be called multiple times. This can happen
* This can be retrived by calling the static method getBuildDate() * if someone manually calls this and then a finalizer calls it.
* @see getBuildDate()
*/ */
private static String buildDate = ""; public void safeRelease() {
// currently does nothing - subclasses may do something
/** if (isDebugEnabled()) {
* Standard constructor that adds this JacobObject // this used to do a toString() but that is bad for SafeArray
* to the memory management pool. debug("SafeRelease: " + this.getClass().getName());
*/ }
public JacobObject() { }
ROT.addObject(this);
}
/**
/** * When things go wrong, it is useful to be able to debug the ROT.
* Loads version information from version.properties that was */
* built as part of this release. private static final boolean DEBUG =
* // true;
*/ "true".equalsIgnoreCase(System.getProperty("com.jacob.debug"));
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;
}
/** protected static boolean isDebugEnabled() {
* loads version.properties and returns the value of versin in it // return true;
* @return String value of version in version.properties or "" if none return DEBUG;
*/ }
public static String getBuildVersion(){
if (buildVersion.equals("")){ /**
loadVersionProperties(); * Loads JacobVersion.Properties and returns the value of version in it
} *
return buildVersion; * @deprecated use JacobReleaseInfo.getBuildDate() instead.
} * @return String value of version in JacobVersion.Properties or "" if none
*/
/** @Deprecated
* Finalizers call this method. public static String getBuildDate() {
* This method should release any COM data structures in a way return JacobReleaseInfo.getBuildDate();
* that it can be called multiple times. }
* This can happen if someone manually calls this and then
* a finalizer calls it. /**
*/ * Loads JacobVersion.Properties and returns the value of version in it
public void safeRelease() { *
// currently does nothing - subclasses may do something * @deprecated use JacobReleaseInfo.getBuildVersion() instead.
if (isDebugEnabled()){ * @return String value of version in JacobVersion.Properties or "" if none
// this used to do a toString() but that is bad for SafeArray */
debug("SafeRelease: "+this.getClass().getName()); @Deprecated
} public static String getBuildVersion() {
} return JacobReleaseInfo.getBuildVersion();
}
/**
* When things go wrong, it is usefull to be able to debug the ROT. /**
*/ * Very basic debugging function.
private static final boolean DEBUG = *
//true; * @param istrMessage
"true".equalsIgnoreCase(System.getProperty("com.jacob.debug")); */
protected static void debug(String istrMessage) {
protected static boolean isDebugEnabled(){ if (isDebugEnabled()) {
//return true; System.out.println(istrMessage + " in thread "
return DEBUG; + Thread.currentThread().getName());
} }
/** }
* Very basic debugging fucntion.
* @param istrMessage /**
*/ * force the jacob DLL to be loaded whenever this class is referenced
protected static void debug(String istrMessage) */
{ static {
if(isDebugEnabled()) LibraryLoader.loadJacobLibrary();
{ }
System.out.println(istrMessage
+ " in thread "+ Thread.currentThread().getName());
}
}
/**
* force the jacob DLL to be loaded whenever this class is referenced
*/
static {
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>If system property {@link #JACOB_DLL_PATH} is defined, the file located there
* will be loaded as the jacob dll. If the system property is not defined, normal
* library paths will be used to load the jacob dll. This means it defaults to the
* previous behavior for existing applications.
* <p> * <p>
* The standard behavior for most applications is that LoadLibrary() will be called *
* to load the dll. LoadLibary searches directories specified in the variable * This supports defining the path or library name using system properties or a
* java.library.path . This is why most test cases specify -Djava.library.path in * custom resource file. If desired, jacob can auto-detect the correct version
* their command line arguments * of the DLL for 32 or 64 bit windows, as long as you have named them
* 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>
* Submitted sourceforge ticket 1493647 * JACOB_DLL_PATH submitted sourceforge ticket 1493647 Added 1.11 <br>
* JACOB_DLL_NAME, JACOB_DLL_NAME_32, JACOB_DLL_NAME_64 submitted sourceforge
* ticket 1845039 Added 1.14M7
*
* @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 {
else { // Path was not defined, so use the OS mechanism for loading
System.loadLibrary("jacob"); // 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();
}
// 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,24 +20,22 @@
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 {
/** /**
* *
*/ */
private static final long serialVersionUID = -9169900832852356445L; private static final long serialVersionUID = -9169900832852356445L;
/** /**
* @param description * @param description
*/ */
public NotImplementedException(String description) { public NotImplementedException(String description) {
super(description); super(description);
} }
} }

View File

@@ -28,194 +28,210 @@ import java.util.WeakHashMap;
* The Running Object Table (ROT) maps each thread to a collection of all the * The Running Object Table (ROT) maps each thread to a collection of all the
* JacobObjects that were created in that thread. It always operates on the * JacobObjects that were created in that thread. It always operates on the
* current thread so all the methods are static and they implicitly get the * current thread 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);
} }
return getThreadObjects( false ); return getThreadObjects(false);
} }
/** /**
* 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();
// remove the collection from rot // remove the collection from rot
rot.remove( Thread.currentThread().getName() ); rot.remove(Thread.currentThread().getName());
if ( JacobObject.isDebugEnabled() ) { if (JacobObject.isDebugEnabled()) {
JacobObject.debug( "ROT: thread table cleared and removed" ); JacobObject.debug("ROT: thread table cleared and removed");
} }
} else { } else {
if ( JacobObject.isDebugEnabled() ) { if (JacobObject.isDebugEnabled()) {
JacobObject.debug( "ROT: nothing to clear!" ); JacobObject.debug("ROT: nothing to clear!");
} }
} }
} }
/** /**
* @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
*/ */
protected synchronized static void removeObject( JacobObject o ) { @Deprecated
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);
} }
o.safeRelease(); o.safeRelease();
} }
/** /**
* 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()
if (shouldIncludeClassInROT.equalsIgnoreCase("false")){ + PUT_IN_ROT_SUFFIX, "true");
if (JacobObject.isDebugEnabled()){ if (shouldIncludeClassInROT.equalsIgnoreCase("false")) {
JacobObject.debug("JacobObject: New instance of "+o.getClass().getName()+" not added to ROT"); if (JacobObject.isDebugEnabled()) {
} JacobObject.debug("JacobObject: New instance of "
} else { + o.getClass().getName() + " not added to ROT");
Map tab = getThreadObjects( false ); }
if ( tab == null ) { } else {
Map<JacobObject, String> tab = getThreadObjects(false);
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
ComThread.InitMTA( false ); ComThread.InitMTA(false);
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);
} }
} }
} }
/** /**
* 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

@@ -25,74 +25,77 @@ package com.jacob.com;
* component that wants to run in an STA other than the main STA. * component that wants to run in an STA other than the main STA.
*/ */
public class STA extends Thread { public class STA extends Thread {
/** /**
* referenced by STA.cpp * referenced by STA.cpp
*/ */
public int threadID; public int threadID;
/** /**
* constructor for STA * constructor for STA
*/ */
public STA() { public STA() {
start(); // start the thread start(); // start the thread
} }
/* (non-Javadoc) /*
* @see java.lang.Thread#run() * (non-Javadoc)
*/ *
public void run() { * @see java.lang.Thread#run()
// init COM */
ComThread.InitSTA(); public void run() {
if (OnInit()) { // init COM
// this call blocks in the win32 message loop ComThread.InitSTA();
// until quitMessagePump is called if (OnInit()) {
doMessagePump(); // this call blocks in the win32 message loop
} // until quitMessagePump is called
OnQuit(); doMessagePump();
// uninit COM }
ComThread.Release(); OnQuit();
} // uninit COM
ComThread.Release();
}
/** /**
* 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() { */
return true; public boolean OnInit() {
} return true;
}
/** /**
* Override this method to destroy any resource before the thread exits and * Override this method to destroy any resource before the thread exits and
* COM in uninitialized * COM in uninitialized
*/ */
public void OnQuit() { public void OnQuit() {
// there is nothing to see here // there is nothing to see here
} }
/** /**
* calls quitMessagePump * calls quitMessagePump
*/ */
public void quit() { public void quit() {
quitMessagePump(); quitMessagePump();
} }
/** /**
* run a message pump for the main STA * run a message pump for the main STA
*/ */
public native void doMessagePump(); public native void doMessagePump();
/** /**
* quit message pump for the main STA * quit message pump for the main STA
*/ */
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

@@ -19,15 +19,16 @@
*/ */
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 {
public VariantViaEvent(){ /**
super(); * Standard constructor used by JNI event handling layer
} */
public VariantViaEvent() {
super();
}
} }

View File

@@ -23,24 +23,25 @@ package com.jacob.com;
* thrown in util.cpp * thrown in util.cpp
*/ */
public class WrongThreadException extends JacobException { public class WrongThreadException extends JacobException {
/** /**
* identifier generated by Eclipse * identifier generated by Eclipse
*/ */
private static final long serialVersionUID = 6308780364980228692L; private static final long serialVersionUID = 6308780364980228692L;
/** /**
* standard 0 arg constructor with no message * standard 0 arg constructor with no message
* *
*/ */
public WrongThreadException() { public WrongThreadException() {
super("No Message Provided."); super("No Message Provided.");
} }
/** /**
* standard constructor with a string message * standard constructor with a string message
* @param s *
*/ * @param s
public WrongThreadException(String s) { */
super(s); public WrongThreadException(String s) {
} super(s);
}
} }

View File

@@ -4,56 +4,112 @@ 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 {
public void testActiveXComponentFactory(){ /**
* 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() {
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
if (mTryConnectingFirst != null ){ .connectToActiveInstance(mApplicationId);
mTryConnectingFirst.invoke("Quit",new Variant[] {}); if (mTryConnectingFirst != null) {
System.out.println("Was able to connect to MSWord when hadn't started it"); mTryConnectingFirst.invoke("Quit", new Variant[] {});
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
if (mTryStartingSecond == null){ .createNewInstance(mApplicationId);
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
if (mTryConnectingThird == null ){ .connectToActiveInstance(mApplicationId);
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 {
System.out.println("Stopping MSWord"); System.out.println("Stopping MSWord");
// stop it so we can fail trying to connect to a running // stop it so we can fail trying to connect to a running
mTryConnectingThird.invoke("Quit",new Variant[] {}); mTryConnectingThird.invoke("Quit", new Variant[] {});
} }
Thread.sleep(2000); Thread.sleep(2000);
ActiveXComponent mTryConnectingFourth = ActiveXComponent.connectToActiveInstance(mApplicationId); ActiveXComponent mTryConnectingFourth = ActiveXComponent
if (mTryConnectingFourth != null ){ .connectToActiveInstance(mApplicationId);
mTryConnectingFourth.invoke("Quit",new Variant[] {}); if (mTryConnectingFourth != null) {
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
//Thread.sleep(2000); // in the glory of this success");
// Thread.sleep(2000);
ComThread.Release(); ComThread.Release();
ComThread.quitMainSTA(); ComThread.quitMainSTA();
} }

View File

@@ -9,37 +9,45 @@ 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 {
public void testDateUtilities(){ /**
Date now = new Date(); * verify date conversion to and from java
double comTimeForNow = DateUtilities.convertDateToWindowsTime(now); */
Date retrievedNow = DateUtilities.convertWindowsTimeToDate(comTimeForNow); public void testDateUtilities() {
if (!now.equals(retrievedNow)){ Date now = new Date();
fail("DateUtilities Date Test failed " +now+ " != " +retrievedNow ); double comTimeForNow = DateUtilities.convertDateToWindowsTime(now);
} else { Date retrievedNow = DateUtilities
System.out.println("DateUtilities Date Test passed"); .convertWindowsTimeToDate(comTimeForNow);
} if (!now.equals(retrievedNow)) {
fail("DateUtilities Date Test failed " + now + " != "
} + retrievedNow);
} else {
public void testBeginningOfWindowsTime(){ System.out.println("DateUtilities Date Test passed");
// this is a magic time in the windows world }
Date beginningOfWindowsTime =
new GregorianCalendar(1899, Calendar.DECEMBER, 30).getTime(); }
double comTimeForBeginningOfWindowsTime =
DateUtilities.convertDateToWindowsTime(beginningOfWindowsTime); /**
if (comTimeForBeginningOfWindowsTime > 0){ * Verify that the start of time is when we think it is.
fail("Beginning of windows time test failed " */
+comTimeForBeginningOfWindowsTime); public void testBeginningOfWindowsTime() {
} else { // this is a magic time in the windows world
System.out.println("Beginning of windows time test passed"); Date beginningOfWindowsTime = new GregorianCalendar(1899,
} Calendar.DECEMBER, 30).getTime();
double comTimeForBeginningOfWindowsTime = DateUtilities
} .convertDateToWindowsTime(beginningOfWindowsTime);
if (comTimeForBeginningOfWindowsTime > 0) {
fail("Beginning of windows time test failed "
+ comTimeForBeginningOfWindowsTime);
} else {
System.out.println("Beginning of windows time test passed");
}
}
} }

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 {
public void testNullProgramId(){ /**
* Verify that dispatch constructors are protected from null program ids.
*/
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 {
public void testDispatch() { /**
Date testDate = new Date(); * Dummy test until someone gets their act together
Variant fromDate = Dispatch.obj2variant(testDate); */
Date returnedDate = fromDate.getJavaDate(); public void testDispatch() {
//System.out.println("test date is "+testDate); // what should we test
//System.out.println("VariantDate is "+fromDate.getJavaDate()); }
assertTrue("Could not call obj2variant(Date) and get it to work",
testDate.equals(returnedDate));
}
} }

View File

@@ -4,27 +4,38 @@ 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 {
public void testThrowIllegalArgumentException() { /**
try { * force an IllegalArgumentException to verify the utility method throws
Dispatch.call(null, 0); * correctly.
fail("Failed to throw IllegalArgumentException"); */
} catch (IllegalArgumentException iae){ public void testThrowIllegalArgumentException() {
System.out.println("Caught correct IllegalArgumentException: "+iae); try {
} Dispatch.call(null, 0);
} fail("Failed to throw IllegalArgumentException");
public void testThrowIllegalStateException() { } catch (IllegalArgumentException iae) {
try { System.out.println("Caught correct IllegalArgumentException: "
Dispatch foo = new Dispatch(); + iae);
Dispatch.call(foo, 0); }
fail("Failed to throw IllegalStateException"); }
} catch (IllegalStateException ise){
System.out.println("Caught correct IllegalStateException "+ise); /**
} * force an IllegalStateException to verify the utility method throws
} * correctly.
*/
public void testThrowIllegalStateException() {
try {
Dispatch foo = new Dispatch();
Dispatch.call(foo, 0);
fail("Failed to throw IllegalStateException");
} catch (IllegalStateException ise) {
System.out.println("Caught correct IllegalStateException " + ise);
}
}
} }

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 {
/**
public void testBuildVersion(){ * verify the build version and date functions work correctly
System.out.println("build version is "+JacobObject.getBuildVersion()); */
System.out.println("build date is "+JacobObject.getBuildDate()); public void testBuildVersion() {
} System.out.println("build version is " + JacobReleaseInfo.getBuildVersion());
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,9 +100,8 @@ 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,121 +1,133 @@
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. A
* verify the SystemProperty (classname).PutInROT functions as expected. * value of false means instances of the class are not put in the ROT Any o
* A value of false means instances of the class are not put in the ROT * ther value means they are
* Any o 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
// class to load and any pre-defined Variants (FALSE and TRUE) to be created immediately // 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()
int countPriorToTest = ROT.getThreadObjects(true).entrySet().size(); + ROT.PUT_IN_ROT_SUFFIX, "false");
new VariantViaEvent(); int countPriorToTest = ROT.getThreadObjects(true).entrySet().size();
int countAfterAddWithoutROT = ROT.getThreadObjects(true).entrySet().size(); new VariantViaEvent();
if (countAfterAddWithoutROT != countPriorToTest){ int countAfterAddWithoutROT = ROT.getThreadObjects(true).entrySet()
debug("Failure: count prior: "+countPriorToTest+ .size();
" and count after without ROT was: "+countAfterAddWithoutROT); if (countAfterAddWithoutROT != countPriorToTest) {
} debug("Failure: count prior: " + countPriorToTest
+ " and count after without ROT was: "
System.setProperty(VariantViaEvent.class.getName()+ROT.PUT_IN_ROT_SUFFIX,"true"); + countAfterAddWithoutROT);
new VariantViaEvent(); }
int countAfterAddWithROT = ROT.getThreadObjects(true).entrySet().size();
if (countAfterAddWithROT != (countPriorToTest+1)){
debug("Failure: count prior: "+countPriorToTest+
" and count after with ROT was: "+countAfterAddWithROT);
}
debug("testDontFillROTSystemProperty: completed");
}
/** System.setProperty(VariantViaEvent.class.getName()
* Needs documentation. This test looks broken + ROT.PUT_IN_ROT_SUFFIX, "true");
* new VariantViaEvent();
*/ int countAfterAddWithROT = ROT.getThreadObjects(true).entrySet().size();
public void testGCBehavior(){ if (countAfterAddWithROT != (countPriorToTest + 1)) {
int sizeBeforeBuild = 0; debug("Failure: count prior: " + countPriorToTest
int sizeAfterBuild = 0; + " and count after with ROT was: " + countAfterAddWithROT);
int sizeBeforeGC = 0; }
int sizeAfterGC = 0; debug("testDontFillROTSystemProperty: completed");
int loopSize = 10000; }
int sizeExpectedAfterBuild = 0;
/**
debug("testGCBehavior: started"); * Needs documentation. This test looks broken
debug("creating 10,000 object sets"); *
// cause classes to get loaded and any static instances to be created */
SafeArray.class.getName(); public void testGCBehavior() {
Variant.class.getName(); int sizeBeforeBuild = 0;
sizeBeforeBuild = ROT.getThreadObjects(false).size(); int sizeAfterBuild = 0;
sizeExpectedAfterBuild = ((loopSize*3)+sizeBeforeBuild); int sizeBeforeGC = 0;
for ( int i = 0 ; i < loopSize; i++){ int sizeAfterGC = 0;
SafeArray a1 = new SafeArray(Variant.VariantVariant, 2); int loopSize = 10000;
a1.setVariant(0, new Variant("foo")); int sizeExpectedAfterBuild = 0;
a1.setVariant(1, new Variant("bar"));
} debug("testGCBehavior: started");
sizeAfterBuild = ROT.getThreadObjects(false).size(); debug("creating 10,000 object sets");
if (sizeAfterBuild < sizeExpectedAfterBuild){ // cause classes to get loaded and any static instances to be created
debug("Something got GC'd: "+sizeAfterBuild); SafeArray.class.getName();
} else if (sizeAfterBuild > sizeExpectedAfterBuild){ Variant.class.getName();
debug("More: "+sizeAfterBuild+" than expected: "+sizeExpectedAfterBuild); sizeBeforeBuild = ROT.getThreadObjects(false).size();
} else { sizeExpectedAfterBuild = ((loopSize * 3) + sizeBeforeBuild);
debug("They're all there"); for (int i = 0; i < loopSize; i++) {
} SafeArray a1 = new SafeArray(Variant.VariantVariant, 2);
// add more to the VM a1.setVariant(0, new Variant("foo"));
debug("Flooding Memory to force GC"); a1.setVariant(1, new Variant("bar"));
for ( int i = 0 ; i <= loopSize*2; i++){ }
new String("this is just some text to see if we can force gc "+i); sizeAfterBuild = ROT.getThreadObjects(false).size();
} if (sizeAfterBuild < sizeExpectedAfterBuild) {
// storage will hold weak references until the next JacobObject is created debug("Something got GC'd: " + sizeAfterBuild);
System.gc(); } else if (sizeAfterBuild > sizeExpectedAfterBuild) {
sizeBeforeGC = ROT.getThreadObjects(false).size(); debug("More: " + sizeAfterBuild + " than expected: "
debug("Objects left after flood and gc but before adding a new object that clean's up weak references: "+sizeBeforeGC); + sizeExpectedAfterBuild);
debug("Creating single object. This adds one and causes ROT to clean up GC'd"); } else {
new JacobObject(); debug("They're all there");
sizeAfterGC = ROT.getThreadObjects(false).size(); }
debug("Objects left after adding one (caused weak ref objects to be removed): "+sizeAfterGC); // add more to the VM
new JacobObject(); debug("Flooding Memory to force GC");
if (ROT.getThreadObjects(false).size() != sizeAfterGC+1){ for (int i = 0; i <= loopSize * 2; i++) {
debug("Unexpected number of objects after adding only one more "+ROT.getThreadObjects(false).size()); new String("this is just some text to see if we can force gc " + i);
} else { }
debug("Found number expected after adding one more " +(sizeAfterGC+1) ); // storage will hold weak references until the next JacobObject is
} // created
ROT.clearObjects(); System.gc();
if (ROT.getThreadObjects(false) == null){ sizeBeforeGC = ROT.getThreadObjects(false).size();
debug("ROT pool was destroyed as expected after clearObjects called."); debug("Objects left after flood and gc but before adding a new object that clean's up weak references: "
} else { + sizeBeforeGC);
debug("ROT pool for thread still exists when it shouldn't"); debug("Creating single object. This adds one and causes ROT to clean up GC'd");
} new JacobObject();
sizeAfterGC = ROT.getThreadObjects(false).size();
//========= part two ================================ debug("Objects left after adding one (caused weak ref objects to be removed): "
debug("Verifying doesn't blow up with double release"); + sizeAfterGC);
for ( int i = 0 ; i <= 10000; i++){ new JacobObject();
new JacobObject(); if (ROT.getThreadObjects(false).size() != sizeAfterGC + 1) {
} debug("Unexpected number of objects after adding only one more "
// force safeRelease call on all objects + ROT.getThreadObjects(false).size());
ROT.clearObjects(); } else {
// now force the gc to go collect them, running safeRelease again debug("Found number expected after adding one more "
System.gc(); + (sizeAfterGC + 1));
debug("testGCBehavior: finished"); }
} ROT.clearObjects();
if (ROT.getThreadObjects(false) == null) {
private static void debug(String message){ debug("ROT pool was destroyed as expected after clearObjects called.");
System.out.println(Thread.currentThread().getName()+" "+message); } else {
} debug("ROT pool for thread still exists when it shouldn't");
}
// ========= part two ================================
debug("Verifying doesn't blow up with double release");
for (int i = 0; i <= 10000; i++) {
new JacobObject();
}
// force safeRelease call on all objects
ROT.clearObjects();
// now force the gc to go collect them, running safeRelease again
System.gc();
debug("testGCBehavior: finished");
}
private static void debug(String message) {
System.out.println(Thread.currentThread().getName() + " " + message);
}
} }

View File

@@ -7,53 +7,64 @@ 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 {
public void testVariantDate() { /**
Date now = new Date(); * verify the conversion of Variants into java dates
Variant holder = new Variant(); */
holder.putDate(now); public void testVariantDate() {
Date retrievedNow = holder.getJavaDate(); Date now = new Date();
if (!now.equals(retrievedNow)){ Variant holder = new Variant();
fail("Variant Date Test failed " +now+ " != " +retrievedNow ); holder.putDate(now);
} else { Date retrievedNow = holder.getJavaDate();
System.out.println("Variant Date Test passed"); if (!now.equals(retrievedNow)) {
} fail("Variant Date Test failed " + now + " != " + retrievedNow);
} else {
} System.out.println("Variant Date Test passed");
}
public void testVariantDateToJavaObject(){
Date now = new Date(); }
Variant holder = new Variant(now);
for ( int i = 0; i < 30000; i++){ /**
Variant dateVariant = new Variant(now); * verify that the Variant constructor accepts Java dates and converts them
Date retrievedNow = holder.getJavaDate(); * correctly
retrievedNow = dateVariant.getJavaDate(); */
if (!now.equals(retrievedNow)){ public void testVariantDateToJavaObject() {
fail("Variant Date Test (1) failed " +now+ " != " +retrievedNow ); Date now = new Date();
} else { Variant holder = new Variant(now);
//System.out.println("Variant Date Test (1) passed"); for (int i = 0; i < 30000; i++) {
} Variant dateVariant = new Variant(now);
// verify auto typecasting works Date retrievedNow = holder.getJavaDate();
retrievedNow = (Date)dateVariant.toJavaObject(); retrievedNow = dateVariant.getJavaDate();
if (!now.equals(retrievedNow)){ if (!now.equals(retrievedNow)) {
fail("Variant Date Test (2) failed " +now+ " != " +retrievedNow ); fail("Variant Date Test (1) failed " + now + " != "
} else { + retrievedNow);
//System.out.println("Variant Date Test (2) passed "+retrievedNow); } else {
} // System.out.println("Variant Date Test (1) passed");
}
Variant intVariant = new Variant(4); // verify auto typecasting works
Object variantReturn = intVariant.toJavaObject(); retrievedNow = (Date) dateVariant.toJavaObject();
// degenerate test to make sure date isn't always returned if (!now.equals(retrievedNow)) {
if (variantReturn instanceof Date ){ fail("Variant Date Test (2) failed " + now + " != "
System.out.println("int variant returned date"); + retrievedNow);
} } else {
} // System.out.println("Variant Date Test (2) passed
System.out.print("Test finished. All tests passed."); // "+retrievedNow);
}
}
Variant intVariant = new Variant(4);
Object variantReturn = intVariant.toJavaObject();
// degenerate test to make sure date isn't always returned
if (variantReturn instanceof Date) {
System.out.println("int variant returned date");
}
}
System.out.print("Test finished. All tests passed.");
}
} }

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,474 +10,658 @@ 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() {
Variant v = null; Variant v = null;
Variant vByRef = null; Variant vByRef = null;
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);
vByRef = new Variant(new Boolean(true),true);
if (!v.toJavaObject().equals(vByRef.toJavaObject())){
fail(v.toString() + " could not make type "
+ v.getvt() +" and "+ vByRef.getvt()
+" java objects come out the same");
}
v = new Variant(new Integer(53),false);
vByRef = new Variant(new Integer(53),true);
if (!v.toJavaObject().equals(vByRef.toJavaObject())){
fail(v.toString() + " could not make type "
+ v.getvt() +" and "+ vByRef.getvt()
+" java objects come out the same");
}
v = new Variant(new Short((short)53),false);
vByRef = new Variant(new Short((short)53),true);
if (!v.toJavaObject().equals(vByRef.toJavaObject())){
fail(v.toString() + " could not make type "
+ v.getvt() +" and "+ vByRef.getvt()
+" java objects come out the same");
} }
v = new Variant("53.33",false); v = new Variant(new Boolean(true), false);
vByRef = new Variant("53.33",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);
vByRef = new Variant(new Integer(53), true);
if (!v.toJavaObject().equals(vByRef.toJavaObject())) {
fail(v.toString() + " could not make type " + v.getvt() + " and "
+ vByRef.getvt() + " java objects come out the same");
}
v = new Variant(new Short((short) 53), false);
vByRef = new Variant(new Short((short) 53), true);
if (!v.toJavaObject().equals(vByRef.toJavaObject())) {
fail(v.toString() + " could not make type " + v.getvt() + " and "
+ vByRef.getvt() + " java objects come out the same");
}
v = new Variant("53.33", false);
vByRef = new Variant("53.33", true);
if (!v.toJavaObject().equals(vByRef.toJavaObject())) {
fail(v.toString() + " could not make type " + v.getvt() + " and "
+ vByRef.getvt() + " 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
// 53.53 had a scale of 64 and 53.52 had a scale of 47 // 53.53 had a scale of 64 and 53.52 had a scale of 47
BigDecimal testDecimal = new BigDecimal(53.50); BigDecimal testDecimal = new BigDecimal(53.50);
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");
} }
// need to do currency also
} }
/**
* 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
// 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());
}
/** /**
* 4/2007 bug report toObject on dispatch tries to call getDispatchRef * 4/2007 bug report toObject on dispatch tries to call getDispatchRef
* instead of getDispatch so toString() on dispatch blows up. * instead of getDispatch so toString() on dispatch blows up.
* *
*/ */
public void testDispatchToJavaObject(){ public void testDispatchToJavaObject() {
Variant v2 = new Variant(); Variant v2 = new Variant();
v2.putNothing(); v2.putNothing();
// this test fails even though the exact same code below works fine // this test fails even though the exact same code below works fine
//v2.toJavaObject(); // v2.toJavaObject();
} }
/** /**
* see what happens when we conver to by ref * see what happens when we conver to by ref
* *
*/ */
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();
short modifier; short modifier;
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!
modifier = Variant.VariantByref | Variant.VariantShort; modifier = Variant.VariantByref | Variant.VariantShort;
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());
);
} }
} }
/** /**
* make sure variant with no backing store works. * make sure variant with no backing store works.
* *
*/ */
public void testUninitializedVariant(){ public void testUninitializedVariant() {
Variant v; Variant v;
// Variants created without parameters are auto set to VariantEmpty // Variants created without parameters are auto set to VariantEmpty
v = new Variant(); v = new Variant();
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
*/ */
public void testToStringDoesNotConvert(){ public void testToStringDoesNotConvert() {
Variant v; Variant v;
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");
} }
if (v.getBoolean() != true){ if (v.getBoolean() != true) {
fail("toString() converted boolean true to "+ v.getBoolean()); fail("toString() converted boolean true to " + v.getBoolean());
} }
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");
} }
if (v.getBoolean() != false){ if (v.getBoolean() != false) {
fail("toString() converted boolean false to "+ v.getBoolean()); fail("toString() converted boolean false to " + v.getBoolean());
} }
} }
public void testSafeReleaseBoolean(){ /**
* Verify that booleans can be released. Part of the suite that checks all
* types.
*/
public void testSafeReleaseBoolean() {
Variant v; Variant v;
v = new Variant(true); v = new Variant(true);
//System.out.println("Newly created Variant ("+ v.getBoolean()+") "+ // System.out.println("Newly created Variant ("+ v.getBoolean()+") "+
// "trying to create access violation but it doesn't seem to be easy"); // "trying to create access violation but it doesn't seem to be easy");
v.safeRelease(); v.safeRelease();
try { try {
v.getBoolean(); v.getBoolean();
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++) {
new Variant ("xxx"+i); new Variant("xxx" + i);
new Variant(i); new Variant(i);
new Variant ("yyy"+i); new Variant("yyy" + i);
} }
ComThread.Release(); ComThread.Release();
try { try {
v.getBoolean(); v.getBoolean();
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");
} }
} }
/** /**
* verify the constant values aren't released with safeRelease * verify the constant values aren't released with safeRelease
* *
*/ */
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()");
throw new RuntimeException("test failed"); throw new RuntimeException("test failed");
} else { } else {
//System.out.println("VT_TRUE survived SafeRelease()"); // System.out.println("VT_TRUE survived SafeRelease()");
} }
for ( int i = 0 ; i < 10; i ++){ for (int i = 0; i < 10; i++) {
new Variant ("xxx"+i); new Variant("xxx" + i);
new Variant(i); new Variant(i);
new Variant ("yyy"+i); new Variant("yyy" + i);
} }
ComThread.Release(); ComThread.Release();
if (Variant.VT_TRUE.getBoolean() != true){ if (Variant.VT_TRUE.getBoolean() != true) {
fail("VT_TRUE has been broken by ComThread.Release()"); fail("VT_TRUE has been broken by ComThread.Release()");
throw new RuntimeException("test failed"); throw new RuntimeException("test failed");
} else { } else {
//System.out.println("VT_TRUE survived ComThread.Release()"); // System.out.println("VT_TRUE survived ComThread.Release()");
} }
} }
/** /**
* 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() {
String mTestString = "Guitar Hero"; String mTestString = "Guitar Hero";
Variant v = new Variant(mTestString); Variant v = new Variant(mTestString);
//System.out.println("Newly created Variant ("+ v.getString()+") "+ // System.out.println("Newly created Variant ("+ v.getString()+") "+
// "about to safe release and then access"); // "about to safe release and then access");
v.safeRelease(); v.safeRelease();
try { try {
v.getString(); v.getString();
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");
} }
} }
/** /**
* verifies objectIsAConstant works as expected * verifies objectIsAConstant works as expected
* *
*/ */
public void testObjectIsAConstant(){ public void testObjectIsAConstant() {
Variant v = new Variant("d"); Variant v = new Variant("d");
if (!v.objectIsAConstant(Variant.VT_FALSE)){ if (!v.objectIsAConstant(Variant.VT_FALSE)) {
fail("did not recognize VT_FALSE"); fail("did not recognize VT_FALSE");
} }
if (!v.objectIsAConstant(Variant.VT_TRUE)){ if (!v.objectIsAConstant(Variant.VT_TRUE)) {
fail("did not recognize VT_TRUE"); fail("did not recognize VT_TRUE");
} }
if (!v.objectIsAConstant(Variant.VT_MISSING)){ if (!v.objectIsAConstant(Variant.VT_MISSING)) {
fail("did not recognize VT_MISSING"); fail("did not recognize VT_MISSING");
} }
if (!v.objectIsAConstant(Variant.DEFAULT)){ if (!v.objectIsAConstant(Variant.DEFAULT)) {
fail("did not recognize DEFAULT"); fail("did not recognize DEFAULT");
} }
if (v.objectIsAConstant(new Variant(true))){ if (v.objectIsAConstant(new Variant(true))) {
fail("confused a boolean with VT_TRUE"); fail("confused a boolean with VT_TRUE");
} }
if (v.objectIsAConstant(new Variant(false))){ if (v.objectIsAConstant(new Variant(false))) {
fail("confused a boolean with VT_FALSE"); fail("confused a boolean with VT_FALSE");
} }
}
}
/** /**
* tests put and get methods looking for obvious defects * tests put and get methods looking for obvious defects
* *
*/ */
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());
v.putByte((byte)30); v.putByte((byte) 30);
assertEquals("byte test failed", (byte)30, v.getByte()); assertEquals("byte test failed", (byte) 30, v.getByte());
v.putFloat(40); v.putFloat(40);
if (v.getFloat() != 40.0){ if (v.getFloat() != 40.0) {
fail("float test failed"); fail("float test failed");
} }
v.putDouble(50); v.putDouble(50);
if (v.getDouble() != 50.0){ if (v.getDouble() != 50.0) {
fail("double test failed"); fail("double test failed");
} }
v.putString("1234.567"); v.putString("1234.567");
assertEquals("string test failed","1234.567", v.getString()); assertEquals("string test failed", "1234.567", v.getString());
v.putBoolean(true); v.putBoolean(true);
assertEquals("failed boolean test(true)",true, v.getBoolean()); assertEquals("failed boolean test(true)", true, v.getBoolean());
v.putBoolean(false); v.putBoolean(false);
assertEquals("failed boolean test(false)",false,v.getBoolean()); assertEquals("failed boolean test(false)", false, v.getBoolean());
long originalValue = 123456789123456789L;
v.putCurrency(new Currency(originalValue));
assertEquals("failed currency test", 123456789123456789L, v
.getCurrency().longValue());
v.putCurrency(123456789123456789L);
assertEquals("failed currency test",123456789123456789L, v.getCurrency());
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();
if (!retrievedDate.equals(ourDate)){ if (!retrievedDate.equals(ourDate)) {
fail("failed java date load and unload"); fail("failed java date load and unload");
} }
v.putNull(); v.putNull();
if (!v.isNull()){ if (!v.isNull()) {
fail("failed detecting set null"); fail("failed detecting set null");
} }
v.putString("something other than null"); v.putString("something other than null");
if (v.isNull()){ if (v.isNull()) {
fail("failed null replacement with string"); fail("failed null replacement with string");
} }
v.putEmpty(); v.putEmpty();
if (!v.isNull()){ if (!v.isNull()) {
fail("failed detecting set empty as null"); fail("failed detecting set empty as null");
} }
v.putString("something other than null"); v.putString("something other than null");
if (v.isNull()){ if (v.isNull()) {
fail("failed empty replacement with string as isNull"); fail("failed empty replacement with string as isNull");
} }
Variant v2 = new Variant(); Variant v2 = new Variant();
v2.putNothing(); v2.putNothing();
if (v2.getvt() != Variant.VariantDispatch){ if (v2.getvt() != Variant.VariantDispatch) {
fail("putNothing was supposed to set the type to VariantDispatch"); fail("putNothing was supposed to set the type to VariantDispatch");
} }
if (!v2.isNull()){ if (!v2.isNull()) {
fail("putNothing is supposed to cause isNull() to return true"); fail("putNothing is supposed to cause isNull() to return true");
} }
// this line blows up in the test above // this line blows up in the test above
if (v2.toJavaObject() == null){ if (v2.toJavaObject() == null) {
fail("putNothing() followed by toJavaObject() should return a Dispatch"); fail("putNothing() followed by toJavaObject() should return a Dispatch");
} }
} }
/** /**
* 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 testManyThreadedInit(){ public void testDecimalConversion() {
VariantInitTestThread threads[] = new VariantInitTestThread[75]; Variant v = new Variant();
v.changeType(Variant.VariantDecimal);
System.out.println("Starting thread test ("+threads.length 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() {
VariantInitTestThread threads[] = new VariantInitTestThread[75];
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;
} while (numComplete < threads.length) {
int numComplete = 0; // give the works time to work
while (numComplete < threads.length){ try {
// give the works time to work Thread.sleep(333);
try { } catch (InterruptedException ie) {
Thread.sleep(333);
} catch (InterruptedException ie){
// do nothing // do nothing
} }
numComplete = 0; numComplete = 0;
for ( int i = 0; i < threads.length; i++){ for (int i = 0; i < threads.length; i++) {
if (threads[i].isComplete){ if (threads[i].isComplete) {
numComplete++; numComplete++;
} }
} }
//System.out.print("["+numComplete+"/"+threads.length+"]"); // System.out.print("["+numComplete+"/"+threads.length+"]");
} }
System.out.println("Finished thread test"); System.out.println("Finished thread test");
} }
/**
* a class to create variants in seperate threads
* @author joe
*
*/
class VariantInitTestThread extends Thread
{
private boolean isComplete = false;
private int initialRunSize = 0;
/**
* @param arg0
*/
public VariantInitTestThread(String newThreadName, int iStartCount)
{
super(newThreadName);
initialRunSize = iStartCount;
}
public boolean isComplete(){ /**
return isComplete; * a class to create variants in separate threads
} *
/** */
* Blow out a bunch of Variants class VariantInitTestThread extends Thread {
* private boolean isComplete = false;
* @see java.lang.Runnable#run()
*/ private int initialRunSize = 0;
public void run()
{ /**
for (int variantIndex = 0; variantIndex < initialRunSize; variantIndex ++ ){ * @param newThreadName
try { * the name for the thread
Thread.yield(); * @param iStartCount
Thread.sleep(0); * number of threads to start with
} catch (InterruptedException ie){ */
public VariantInitTestThread(String newThreadName, int iStartCount) {
super(newThreadName);
initialRunSize = iStartCount;
}
/**
* getter so master can see if thread is done
*
* @return state of complete flag
*/
public boolean isComplete() {
return isComplete;
}
/**
* Blow out a bunch of Variants
*
* @see java.lang.Runnable#run()
*/
public void run() {
for (int variantIndex = 0; variantIndex < initialRunSize; variantIndex++) {
try {
Thread.yield();
Thread.sleep(0);
} catch (InterruptedException ie) {
// do nothing // do nothing
} }
//System.out.println(Thread.currentThread().getName()); // System.out.println(Thread.currentThread().getName());
Variant testSubject = new Variant(variantIndex); Variant testSubject = new Variant(variantIndex);
testSubject.getvt(); testSubject.getvt();
testSubject.getInt(); testSubject.getInt();
} }
isComplete = true; isComplete = true;
} }
} }
} }

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:
@@ -35,10 +38,11 @@ public class BaseTestCase extends TestCase {
/** /**
* this test exists just to test the setup. * this test exists just to test the setup.
*/ */
public void testSetup(){ public void testSetup() {
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();
@@ -65,14 +71,15 @@ public class BaseTestCase extends TestCase {
if (i == -1) { if (i == -1) {
classPackageName = ""; classPackageName = "";
} else { } else {
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;
if (classPackageName.length()> 0){ if (classPackageName.length() > 0) {
fullPathToResource = classPackageName + "^" + resourceName; fullPathToResource = classPackageName + "^" + resourceName;
} else { } else {
fullPathToResource = resourceName; fullPathToResource = resourceName;
@@ -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) {
@@ -129,16 +142,16 @@ 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,12 +162,13 @@ 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);
// requires that the dll be on the library path // requires that the dll be on the library path
//System.loadLibrary(fullLibraryNameWithPath); // System.loadLibrary(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;
@@ -10,41 +11,34 @@ 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,36 +55,83 @@ 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);
} }
} }
public class ExcelEvents extends InvocationProxy {
/** /**
* Constructor so we can create an instance that implements invoke() * Proxy class to verify we receive expected events
*/ */
public ExcelEvents() { public class ExcelEvents extends InvocationProxy {
}
/** private String listenerPrefix = "-";
* Override the invoke method to log all the events so that we don't have to
* implement all of the specific events.
*/
public Variant invoke(String methodName, Variant targetParameter[]) {
System.out.println("Received event from Windows program" + methodName);
return null;
}
} /**
* Constructor so we can create an instance that implements invoke()
*
* @param interfaceIdentifier
* a string that identifies which listener is speaking
*/
public ExcelEvents(String interfaceIdentifier) {
listenerPrefix = interfaceIdentifier;
}
/**
* Override the invoke method to log all the events so that we don't
* have to implement all of the specific events.
*/
public Variant invoke(String methodName, Variant targetParameter[]) {
System.out.println("Received event from " + listenerPrefix + ": "
+ methodName);
return null;
}
}
} }

View File

@@ -6,212 +6,406 @@ 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();
// remove this line and it dies // remove this line and it dies
///ComThread.InitMTA(true); // /ComThread.InitMTA(true);
IETestThread aThread = new IETestThread(); IETestThread aThread = new IETestThread();
aThread.start(); aThread.start();
while (aThread.isAlive()){ while (aThread.isAlive()) {
try { try {
Thread.sleep(1000); Thread.sleep(1000);
} catch (InterruptedException e) { } catch (InterruptedException e) {
// doen with the sleep // doen with the sleep
//e.printStackTrace(); // e.printStackTrace();
} }
} }
System.out.println("Main: Thread quit, about to quit main sta in thread " System.out
+Thread.currentThread().getName()); .println("Main: Thread quit, about to quit main sta in thread "
// this line only does someting if startMainSTA() was called + Thread.currentThread().getName());
ComThread.quitMainSTA(); // this line only does someting if startMainSTA() was called
System.out.println("Main: did quit main sta in thread " ComThread.quitMainSTA();
+Thread.currentThread().getName()); System.out.println("Main: did quit main sta in thread "
+ Thread.currentThread().getName());
if (aThread.threadFailedWithException != null){
fail("caught an unexpected exception "+aThread.threadFailedWithException); if (aThread.threadFailedWithException != null) {
} 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;
/** /**
* holds any caught exception so the main/test case can see them * holds any caught exception so the main/test case can see them
*/ */
public Throwable threadFailedWithException = null; public Throwable threadFailedWithException = null;
public IETestThread(){
super();
}
public void run()
{
// this used to be 5 seconds but sourceforge is slow
int delay = 5000; // msec
// paired with statement below that blows up
ComThread.InitMTA();
ActiveXComponent ie = new ActiveXComponent("InternetExplorer.Application");
try {
Dispatch.put(ie, "Visible", new Variant(true));
Dispatch.put(ie, "AddressBar", new Variant(true));
System.out.println("IETestThread: " + Dispatch.get(ie, "Path"));
Dispatch.put(ie, "StatusText", new Variant("My Status Text"));
System.out.println("IETestThread: About to hookup event listener");
IEEvents ieE = new IEEvents();
new DispatchEvents(ie, ieE,"InternetExplorer.Application.1");
System.out.println("IETestThread: Did hookup event listener");
/// why is this here? Was there some other code here in the past?
Variant optional = new Variant();
optional.putNoParam();
System.out.println("IETestThread: About to call navigate to sourceforge");
Dispatch.call(ie, "Navigate", new Variant("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");
Dispatch.call(ie, "Navigate", new Variant("http://groups.yahoo.com/group/jacob-project"));
System.out.println("IETestThread: Did call navigate to yahoo");
try { Thread.sleep(delay); } catch (Exception e) {}
} catch (Exception e) {
threadFailedWithException = e;
e.printStackTrace();
} catch (Throwable re){
threadFailedWithException = re;
re.printStackTrace();
} finally {
System.out.println("IETestThread: About to send Quit");
ie.invoke("Quit", new Variant[] {});
System.out.println("IETestThread: Did send Quit");
}
// 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
// "OnQuit" that will came after we have released the thread pool
// this is probably messed up because DispatchEvent object will have been
// freed before the callback
// 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
System.out.println("IETestThread: Waiting until we've received the quit callback");
while (!quitHandled){
try { Thread.sleep(delay/5);} catch (InterruptedException e) {}
}
System.out.println("IETestThread: Received the quit callback");
// wait a little while for it to end
//try {Thread.sleep(delay); } catch (InterruptedException e) {}
System.out.println("IETestThread: about to call ComThread.Release in thread " +
Thread.currentThread().getName());
ComThread.Release(); /**
} * constructor for the test thread
*/
public IETestThread() {
super();
}
/** public void run() {
* The events class must be publicly accessable for reflection to work. // this used to be 5 seconds but sourceforge is slow
* The list of available events is located at http://msdn2.microsoft.com/en-us/library/aa768280.aspx int delay = 5000; // msec
*/ // paired with statement below that blows up
public class IEEvents ComThread.InitMTA();
{ ActiveXComponent ie = new ActiveXComponent(
public void BeforeNavigate2(Variant[] args) { "InternetExplorer.Application");
System.out.println("IEEvents Received ("+Thread.currentThread().getName()+"): BeforeNavigate2 "+args.length); try {
} Dispatch.put(ie, "Visible", new Variant(true));
Dispatch.put(ie, "AddressBar", new Variant(true));
System.out.println("IETestThread: " + Dispatch.get(ie, "Path"));
Dispatch.put(ie, "StatusText", new Variant("My Status Text"));
public void CommandStateChange(Variant[] args) { System.out.println("IETestThread: About to hookup event listener");
System.out.println("IEEvents Received ("+Thread.currentThread().getName()+"): CommandStateChange "+args.length); IEEvents ieE = new IEEvents();
} new DispatchEvents(ie, ieE, "InternetExplorer.Application.1");
System.out.println("IETestThread: Did hookup event listener");
// / why is this here? Was there some other code here in the past?
Variant optional = new Variant();
optional.putNoParam();
public void DocumentComplete(Variant[] args) { System.out
System.out.println("IEEvents Received ("+Thread.currentThread().getName()+"): DocumentComplete "+args.length); .println("IETestThread: About to call navigate to sourceforge");
} Dispatch.call(ie, "Navigate", new Variant(
"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");
Dispatch.call(ie, "Navigate", new Variant(
"http://groups.yahoo.com/group/jacob-project"));
System.out.println("IETestThread: Did call navigate to yahoo");
try {
Thread.sleep(delay);
} catch (Exception e) {
}
} catch (Exception e) {
threadFailedWithException = e;
e.printStackTrace();
} catch (Throwable re) {
threadFailedWithException = re;
re.printStackTrace();
} finally {
System.out.println("IETestThread: About to send Quit");
ie.invoke("Quit", new Variant[] {});
System.out.println("IETestThread: Did send Quit");
}
// 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
// "OnQuit" that will came after we have released the thread pool
// this is probably messed up because DispatchEvent object will have
// been
// freed before the callback
// 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
System.out
.println("IETestThread: Waiting until we've received the quit callback");
while (!quitHandled) {
try {
Thread.sleep(delay / 5);
} catch (InterruptedException e) {
}
}
System.out.println("IETestThread: Received the quit callback");
// wait a little while for it to end
// try {Thread.sleep(delay); } catch (InterruptedException e) {}
System.out
.println("IETestThread: about to call ComThread.Release in thread "
+ Thread.currentThread().getName());
public void DownloadBegin(Variant[] args) { ComThread.Release();
System.out.println("IEEvents Received ("+Thread.currentThread().getName()+"): DownloadBegin "+args.length); }
}
public void DownloadComplete(Variant[] args) { /**
System.out.println("IEEvents Received ("+Thread.currentThread().getName()+"): DownloadComplete "+args.length); * The events class must be publicly accessable for reflection to work. The
} * 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 void BeforeNavigate2(Variant[] args) {
System.out.println("IEEvents Received ("
+ Thread.currentThread().getName() + "): BeforeNavigate2 "
+ args.length);
}
public void NavigateError(Variant[] args) { /**
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 CommandStateChange(Variant[] args) {
System.out.println("IEEvents Received ("
+ Thread.currentThread().getName()
+ "): CommandStateChange " + args.length);
}
public void NavigateComplete2(Variant[] args) { /**
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 DocumentComplete(Variant[] args) {
System.out.println("IEEvents Received ("
+ Thread.currentThread().getName() + "): DocumentComplete "
+ args.length);
}
public void NewWindow2(Variant[] args) { /**
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 DownloadBegin(Variant[] args) {
System.out.println("IEEvents Received ("
+ Thread.currentThread().getName() + "): DownloadBegin "
+ args.length);
}
public void OnFullScreen(Variant[] args) { /**
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 DownloadComplete(Variant[] args) {
System.out.println("IEEvents Received ("
+ Thread.currentThread().getName() + "): DownloadComplete "
+ args.length);
}
public void OnMenuBar(Variant[] args) { /**
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 NavigateError(Variant[] args) {
System.out.println("IEEvents Received ("
+ Thread.currentThread().getName() + "): NavigateError "
+ args.length);
}
public void OnQuit(Variant[] args) { /**
System.out.println("IEEvents Received ("+Thread.currentThread().getName()+"): OnQuit "+args.length); * Internet explorer event this proxy can receive
IETestThread.quitHandled = true; *
} * @param args
* the COM Variant objects that this event passes in.
*/
public void NavigateComplete2(Variant[] args) {
System.out.println("IEEvents Received ("
+ Thread.currentThread().getName() + "): NavigateComplete "
+ args.length);
}
public void OnStatusBar(Variant[] args) { /**
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 NewWindow2(Variant[] args) {
System.out.println("IEEvents Received ("
+ Thread.currentThread().getName() + "): NewWindow2 "
+ args.length);
}
public void OnTheaterMode(Variant[] args) { /**
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 OnFullScreen(Variant[] args) {
System.out.println("IEEvents Received ("
+ Thread.currentThread().getName() + "): OnFullScreen "
+ args.length);
}
public void OnToolBar(Variant[] args) { /**
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 OnMenuBar(Variant[] args) {
System.out.println("IEEvents Received ("
+ Thread.currentThread().getName() + "): OnMenuBar "
+ args.length);
}
public void OnVisible(Variant[] args) { /**
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 OnQuit(Variant[] args) {
System.out.println("IEEvents Received ("
+ Thread.currentThread().getName() + "): OnQuit "
+ args.length);
IETestThread.quitHandled = true;
}
public void ProgressChange(Variant[] args) { /**
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 OnStatusBar(Variant[] args) {
System.out.println("IEEvents Received ("
+ Thread.currentThread().getName() + "): OnStatusBar "
+ args.length);
}
public void PropertyChange(Variant[] args) { /**
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 OnTheaterMode(Variant[] args) {
System.out.println("IEEvents Received ("
+ Thread.currentThread().getName() + "): OnTheaterMode "
+ args.length);
}
public void SetSecureLockIcon(Variant[] args) { /**
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 OnToolBar(Variant[] args) {
System.out.println("IEEvents Received ("
+ Thread.currentThread().getName() + "): OnToolBar "
+ args.length);
}
public void StatusTextChange(Variant[] args) { /**
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 OnVisible(Variant[] args) {
System.out.println("IEEvents Received ("
+ Thread.currentThread().getName() + "): OnVisible "
+ args.length);
}
public void TitleChange(Variant[] args) { /**
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 ProgressChange(Variant[] args) {
System.out.println("IEEvents Received ("
+ Thread.currentThread().getName() + "): ProgressChange "
+ args.length);
}
public void WindowClosing(Variant[] args) { /**
System.out.println("IEEvents Received ("+Thread.currentThread().getName()+"): WindowClosing "+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) {
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) {
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) {
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) {
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) {
System.out.println("IEEvents Received ("
+ Thread.currentThread().getName() + "): WindowClosing "
+ args.length);
}
}
} }

View File

@@ -6,213 +6,284 @@ 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 {
public void testIEActiveProxyCallback() { /**
// this line starts the pump but it runs fine without it * the main test method that builds up the connection and runs the test
ComThread.startMainSTA(); */
// remove this line and it dies public void testIEActiveProxyCallback() {
///ComThread.InitMTA(true); // this line starts the pump but it runs fine without it
IETestActiveProxyThread aThread = new IETestActiveProxyThread(); ComThread.startMainSTA();
aThread.start(); // remove this line and it dies
while (aThread.isAlive()){ // /ComThread.InitMTA(true);
try { IETestActiveProxyThread aThread = new IETestActiveProxyThread();
Thread.sleep(1000); aThread.start();
} catch (InterruptedException e) { while (aThread.isAlive()) {
// doen with the sleep try {
//e.printStackTrace(); Thread.sleep(1000);
} } catch (InterruptedException e) {
} // doen with the sleep
System.out.println("Main: Thread quit, about to quit main sta in thread " // e.printStackTrace();
+Thread.currentThread().getName()); }
// this line only does someting if startMainSTA() was called }
ComThread.quitMainSTA(); System.out
System.out.println("Main: did quit main sta in thread " .println("Main: Thread quit, about to quit main sta in thread "
+Thread.currentThread().getName()); + Thread.currentThread().getName());
if (aThread.threadFailedWithException != null){ // this line only does someting if startMainSTA() was called
fail("caught an unexpected exception "+aThread.threadFailedWithException); ComThread.quitMainSTA();
} System.out.println("Main: did quit main sta in thread "
} + Thread.currentThread().getName());
if (aThread.threadFailedWithException != null) {
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;
/** /**
* holds any caught exception so the main/test case can see them * holds any caught exception so the main/test case can see them
*/ */
public Throwable threadFailedWithException = null; public Throwable threadFailedWithException = null;
public IETestActiveProxyThread(){
super();
}
public void run()
{
// this used to be 5 seconds but sourceforge is slow
int delay = 5000; // msec
// paired with statement below that blows up
ComThread.InitMTA();
ActiveXComponent ie = new ActiveXComponent("InternetExplorer.Application");
try {
Dispatch.put(ie, "Visible", new Variant(true));
Dispatch.put(ie, "AddressBar", new Variant(true));
System.out.println("IETestActiveProxyThread: " + Dispatch.get(ie, "Path"));
Dispatch.put(ie, "StatusText", new Variant("My Status Text"));
System.out.println("IETestActiveProxyThread: About to hookup event listener");
IEEventsActiveProxy ieE = new IEEventsActiveProxy();
new ActiveXDispatchEvents(ie, ieE,"InternetExplorer.Application.1");
System.out.println("IETestActiveProxyThread: Did hookup event listener");
/// why is this here? Was there some other code here in the past?
Variant optional = new Variant();
optional.putNoParam();
System.out.println("IETestActiveProxyThread: About to call navigate to sourceforge");
Dispatch.call(ie, "Navigate", new Variant("http://sourceforge.net/projects/jacob-project"));
System.out.println("IETestActiveProxyThread: Did call navigate to sourceforge");
try { 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) {
threadFailedWithException = e;
e.printStackTrace();
} catch (Throwable re){
threadFailedWithException = re;
re.printStackTrace();
} finally {
System.out.println("IETestActiveProxyThread: About to send Quit");
ie.invoke("Quit", new Variant[] {});
System.out.println("IETestActiveProxyThread: Did send Quit");
}
// 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
// "OnQuit" that will came after we have released the thread pool
// this is probably messed up because DispatchEvent object will have been
// freed before the callback
// 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
System.out.println("IETestActiveProxyThread: Waiting until we've received the quit callback");
while (!quitHandled){
try { Thread.sleep(delay/5);} catch (InterruptedException e) {}
}
System.out.println("IETestActiveProxyThread: Received the quit callback");
// wait a little while for it to end
//try {Thread.sleep(delay); } catch (InterruptedException e) {}
System.out.println("IETestActiveProxyThread: about to call ComThread.Release in thread " +
Thread.currentThread().getName());
ComThread.Release(); /** the thread's constructor */
} public IETestActiveProxyThread() {
super();
}
/** public void run() {
* The events class must be publicly accessable for reflection to work. // this used to be 5 seconds but sourceforge is slow
* The list of available events is located at http://msdn2.microsoft.com/en-us/library/aa768280.aspx int delay = 5000; // msec
*/ // paired with statement below that blows up
public class IEEventsActiveProxy ComThread.InitMTA();
{ ActiveXComponent ie = new ActiveXComponent(
public void BeforeNavigate2(Dispatch pDisp, String url, Integer flags, "InternetExplorer.Application");
String targetFrameName, Variant postData, String headers, Boolean cancel) { try {
System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): BeforeNavigate2 "+url); Dispatch.put(ie, "Visible", new Variant(true));
} Dispatch.put(ie, "AddressBar", new Variant(true));
System.out.println("IETestActiveProxyThread: "
+ Dispatch.get(ie, "Path"));
Dispatch.put(ie, "StatusText", new Variant("My Status Text"));
public void CommandStateChange(Integer command, Boolean enable) { System.out
System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): CommandStateChange "+command); .println("IETestActiveProxyThread: About to hookup event listener");
} IEEventsActiveProxy ieE = new IEEventsActiveProxy();
new ActiveXDispatchEvents(ie, ieE, "InternetExplorer.Application.1");
System.out
.println("IETestActiveProxyThread: Did hookup event listener");
// / why is this here? Was there some other code here in the past?
Variant optional = new Variant();
optional.putNoParam();
public void DocumentComplete(Dispatch pDisp, String url) { System.out
System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): DocumentComplete "+url); .println("IETestActiveProxyThread: About to call navigate to sourceforge");
} Dispatch.call(ie, "Navigate", new Variant(
"http://sourceforge.net/projects/jacob-project"));
System.out
.println("IETestActiveProxyThread: Did call navigate to sourceforge");
try {
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) {
threadFailedWithException = e;
e.printStackTrace();
} catch (Throwable re) {
threadFailedWithException = re;
re.printStackTrace();
} finally {
System.out.println("IETestActiveProxyThread: About to send Quit");
ie.invoke("Quit", new Variant[] {});
System.out.println("IETestActiveProxyThread: Did send Quit");
}
// 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
// "OnQuit" that will came after we have released the thread pool
// this is probably messed up because DispatchEvent object will have
// been
// freed before the callback
// 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
System.out
.println("IETestActiveProxyThread: Waiting until we've received the quit callback");
while (!quitHandled) {
try {
Thread.sleep(delay / 5);
} catch (InterruptedException e) {
}
}
System.out
.println("IETestActiveProxyThread: Received the quit callback");
// wait a little while for it to end
// try {Thread.sleep(delay); } catch (InterruptedException e) {}
System.out
.println("IETestActiveProxyThread: about to call ComThread.Release in thread "
+ Thread.currentThread().getName());
public void DownloadBegin() { ComThread.Release();
System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): DownloadBegin "); }
}
public void DownloadComplete() { /**
System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): DownloadComplete "); * The events class must be publicly accessable for reflection to work. The
} * list of available events is located at
* http://msdn2.microsoft.com/en-us/library/aa768280.aspx
*/
public class IEEventsActiveProxy {
public void NavigateComplete2(Dispatch pDisp, String url) { public void BeforeNavigate2(Dispatch pDisp, String url, Integer flags,
System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): NavigateComplete "+url); String targetFrameName, Variant postData, String headers,
} Boolean cancel) {
System.out.println("IEEventsActiveProxy Received ("
+ Thread.currentThread().getName() + "): BeforeNavigate2 "
+ url);
}
public void NavigateError(Dispatch pDispatch, String url, String targetFrameName, Integer statusCode, Boolean Cancel) { public void CommandStateChange(Integer command, Boolean enable) {
System.out.println("IEEvents Received ("+Thread.currentThread().getName()+"): NavigateError "+statusCode); System.out.println("IEEventsActiveProxy Received ("
} + Thread.currentThread().getName()
+ "): CommandStateChange " + command);
}
public void NewWindow2(Dispatch pDisp, Boolean cancel) { public void DocumentComplete(Dispatch pDisp, String url) {
System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): NewWindow2 "+pDisp); System.out.println("IEEventsActiveProxy Received ("
} + Thread.currentThread().getName() + "): DocumentComplete "
+ url);
}
public void OnFullScreen(Boolean fullScreen) { public void DownloadBegin() {
System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): OnFullScreen "+fullScreen); System.out.println("IEEventsActiveProxy Received ("
} + Thread.currentThread().getName() + "): DownloadBegin ");
}
public void OnMenuBar(Boolean menuBar) { public void DownloadComplete() {
System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): OnMenuBar "+menuBar); System.out
} .println("IEEventsActiveProxy Received ("
+ Thread.currentThread().getName()
+ "): DownloadComplete ");
}
public void OnQuit() { public void NavigateComplete2(Dispatch pDisp, String url) {
System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): OnQuit "); System.out.println("IEEventsActiveProxy Received ("
IETestActiveProxyThread.quitHandled = true; + Thread.currentThread().getName() + "): NavigateComplete "
} + url);
}
public void OnStatusBar(Boolean statusBar) { public void NavigateError(Dispatch pDispatch, String url,
System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): OnStatusBar "+statusBar); String targetFrameName, Integer statusCode, Boolean Cancel) {
} System.out.println("IEEvents Received ("
+ Thread.currentThread().getName() + "): NavigateError "
+ statusCode);
}
public void OnTheaterMode(Boolean theaterMode) { public void NewWindow2(Dispatch pDisp, Boolean cancel) {
System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): OnTheaterMode "+theaterMode); System.out.println("IEEventsActiveProxy Received ("
} + Thread.currentThread().getName() + "): NewWindow2 "
+ pDisp);
}
public void OnToolBar(Boolean onToolBar) { public void OnFullScreen(Boolean fullScreen) {
System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): OnToolBar "+onToolBar); System.out.println("IEEventsActiveProxy Received ("
} + Thread.currentThread().getName() + "): OnFullScreen "
+ fullScreen);
}
public void OnVisible(Boolean onVisible) { public void OnMenuBar(Boolean menuBar) {
System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): onVisible "+ onVisible); System.out.println("IEEventsActiveProxy Received ("
} + Thread.currentThread().getName() + "): OnMenuBar "
+ menuBar);
}
public void ProgressChange() { public void OnQuit() {
System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): ProgressChange "); System.out.println("IEEventsActiveProxy Received ("
} + Thread.currentThread().getName() + "): OnQuit ");
IETestActiveProxyThread.quitHandled = true;
}
public void PropertyChange() { public void OnStatusBar(Boolean statusBar) {
System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): PropertyChange "); System.out.println("IEEventsActiveProxy Received ("
} + Thread.currentThread().getName() + "): OnStatusBar "
+ statusBar);
}
public void SetSecureLockIcon(Integer secureLockIcon) { public void OnTheaterMode(Boolean theaterMode) {
System.out.println("IEEvents Received ("+Thread.currentThread().getName()+"): setSecureLockIcon "+secureLockIcon); System.out.println("IEEventsActiveProxy Received ("
} + Thread.currentThread().getName() + "): OnTheaterMode "
+ theaterMode);
}
public void StatusTextChange() { public void OnToolBar(Boolean onToolBar) {
System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): StatusTextChange "); System.out.println("IEEventsActiveProxy Received ("
} + Thread.currentThread().getName() + "): OnToolBar "
+ onToolBar);
}
public void TitleChange() { public void OnVisible(Boolean onVisible) {
System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): TitleChange "); System.out.println("IEEventsActiveProxy Received ("
} + Thread.currentThread().getName() + "): onVisible "
+ onVisible);
}
public void WindowClosing(Boolean isChildWindow) { public void ProgressChange() {
System.out.println("IEEvents Received ("+Thread.currentThread().getName()+"): WindowClosing "+isChildWindow); System.out.println("IEEventsActiveProxy Received ("
} + Thread.currentThread().getName() + "): ProgressChange ");
} }
public void PropertyChange() {
System.out.println("IEEventsActiveProxy Received ("
+ Thread.currentThread().getName() + "): PropertyChange ");
}
public void SetSecureLockIcon(Integer secureLockIcon) {
System.out.println("IEEvents Received ("
+ Thread.currentThread().getName()
+ "): setSecureLockIcon " + secureLockIcon);
}
public void StatusTextChange() {
System.out
.println("IEEventsActiveProxy Received ("
+ Thread.currentThread().getName()
+ "): StatusTextChange ");
}
public void TitleChange() {
System.out.println("IEEventsActiveProxy Received ("
+ Thread.currentThread().getName() + "): TitleChange ");
}
public void WindowClosing(Boolean 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() {
@@ -49,38 +50,44 @@ public class WordEventTest extends BaseTestCase {
// this is different from the ExcelEventTest because it uses // this is different from the ExcelEventTest because it uses
// 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
if (documents == null){ .getPropertyAsComponent("Documents");
if (documents == null) {
fail("unable to get documents"); fail("unable to get documents");
} }
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 + ": " + 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");
}
public class WordEvents extends InvocationProxy {
/**
* Constructor so we can create an instance that implements invoke()
*/
public WordEvents() {
} }
/** /**
* override the invoke() method to log all the events without writing a bunch of code * a class that receives messages from word
*/ */
public Variant invoke(String methodName, Variant targetParameter[]) { public class WordEvents extends InvocationProxy {
System.out.println("Received event from Windows program" + methodName); /**
return null; * Constructor so we can create an instance that implements invoke()
} */
public WordEvents() {
}
} /**
* override the invoke() method to log all the events without writing a
* bunch of code
*/
public Variant invoke(String methodName, Variant targetParameter[]) {
System.out.println("Received event from Windows program"
+ methodName);
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

@@ -1,13 +1,13 @@
package com.jacob.test.powerpoint; package com.jacob.test.powerpoint;
/** /**
* $Id$ * $Id$
* *
* This is really more of a multi threaded tester * This is really more of a multi threaded tester
* <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 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.ActiveXComponent; import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComFailException; import com.jacob.com.ComFailException;
import com.jacob.com.ComThread; import com.jacob.com.ComThread;
@@ -17,117 +17,136 @@ 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
* @param args
*/
public void testPowerpoint() {
ComThread.InitMTA();
ActiveXComponent component = new ActiveXComponent("Powerpoint.Application");
Dispatch comPowerpoint = component.getObject();
try {
PowerpointTestThread[] threads = new PowerpointTestThread[NUM_THREADS];
for (int i=0; i<NUM_THREADS; i++) {
threads[i] = new PowerpointTestThread(i+1, comPowerpoint);
threads[i].start();
}
boolean allThreadsFinished = false;
while (!allThreadsFinished) {
allThreadsFinished = true;
for (int i=0; i<NUM_THREADS; i++) {
if (threads[i].isAlive()) {
allThreadsFinished = false;
break;
}
}
if (!allThreadsFinished) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// no op
}
}
}
Dispatch.call(comPowerpoint,"Quit");
for (int i = 0 ; i < NUM_THREADS; i++){
if (threads[i].threadFailedWithException != null){
fail ("caught unexpected exception in thread "+
threads[i].threadFailedWithException);
}
}
} finally {
ComThread.Release();
}
}
public class PowerpointTestThread extends Thread {
/** /**
* holds any caught exception so the main/test case can see them * main program that lets us run this as a test
*
* @param args
*/ */
public Throwable threadFailedWithException = null; public void testPowerpoint() {
ComThread.InitMTA();
private int threadID;
private Dispatch comPowerpoint; ActiveXComponent component = new ActiveXComponent(
"Powerpoint.Application");
public PowerpointTestThread(int threadID, Dispatch comPowerpoint) { Dispatch comPowerpoint = component.getObject();
super("TestThread "+threadID);
this.threadID = threadID; try {
this.comPowerpoint = comPowerpoint; PowerpointTestThread[] threads = new PowerpointTestThread[NUM_THREADS];
} for (int i = 0; i < NUM_THREADS; i++) {
threads[i] = new PowerpointTestThread(i + 1, comPowerpoint);
public void run() { threads[i].start();
System.out.println("Thread \""+Thread.currentThread().getName()+"\" started"); }
System.out.flush();
ComThread.InitMTA(); boolean allThreadsFinished = false;
try { while (!allThreadsFinished) {
for (int i=0; i<NUM_ITERATIONS; i++) { allThreadsFinished = true;
if (i % 10 == 0) { for (int i = 0; i < NUM_THREADS; i++) {
System.out.println(Thread.currentThread().getName()+": Iteration "+i); if (threads[i].isAlive()) {
System.out.flush(); allThreadsFinished = false;
} break;
Dispatch comPresentations = Dispatch.get(comPowerpoint,"Presentations").toDispatch(); }
Dispatch comPresentation = Dispatch.call(comPresentations, }
"Open", if (!allThreadsFinished) {
getWindowsFilePathToPackageResource("test"+threadID+".ppt",this.getClass()), try {
new Integer(0), Thread.sleep(100);
new Integer(0), } catch (InterruptedException e) {
new Integer(0)).toDispatch(); // no op
Dispatch.call(comPresentation, "Close"); }
} }
} catch (ComFailException cfe){ }
threadFailedWithException = cfe;
System.err.println(Thread.currentThread().getName()+"\" while working on: "+ Dispatch.call(comPowerpoint, "Quit");
getWindowsFilePathToPackageResource("test"+threadID+".ppt",this.getClass())); for (int i = 0; i < NUM_THREADS; i++) {
cfe.printStackTrace(); if (threads[i].threadFailedWithException != null) {
} catch (Exception e) { fail("caught unexpected exception in thread "
threadFailedWithException = e; + threads[i].threadFailedWithException);
System.err.println("Error in Thread \""+Thread.currentThread().getName()+"\":"); }
e.printStackTrace(); }
} finally { } finally {
ComThread.Release(); ComThread.Release();
System.out.println("Thread \""+Thread.currentThread().getName()+"\" finished"); }
System.out.flush();
} }
}
/**
} * the thread class that runs power point
*/
public class PowerpointTestThread extends Thread {
/**
* holds any caught exception so the main/test case can see them
*/
public Throwable threadFailedWithException = null;
private int threadID;
private Dispatch comPowerpoint;
/**
* thread constructor
*
* @param threadID
* @param comPowerpoint
*/
public PowerpointTestThread(int threadID, Dispatch comPowerpoint) {
super("TestThread " + threadID);
this.threadID = threadID;
this.comPowerpoint = comPowerpoint;
}
public void run() {
System.out.println("Thread \"" + Thread.currentThread().getName()
+ "\" started");
System.out.flush();
ComThread.InitMTA();
try {
for (int i = 0; i < NUM_ITERATIONS; i++) {
if (i % 10 == 0) {
System.out.println(Thread.currentThread().getName()
+ ": Iteration " + i);
System.out.flush();
}
Dispatch comPresentations = Dispatch.get(comPowerpoint,
"Presentations").toDispatch();
Dispatch comPresentation = Dispatch.call(
comPresentations,
"Open",
getWindowsFilePathToPackageResource("test"
+ threadID + ".ppt", this.getClass()),
new Integer(0), new Integer(0), new Integer(0))
.toDispatch();
Dispatch.call(comPresentation, "Close");
}
} catch (ComFailException cfe) {
threadFailedWithException = cfe;
System.err.println(Thread.currentThread().getName()
+ "\" while working on: "
+ getWindowsFilePathToPackageResource("test" + threadID
+ ".ppt", this.getClass()));
cfe.printStackTrace();
} catch (Exception e) {
threadFailedWithException = e;
System.err.println("Error in Thread \""
+ Thread.currentThread().getName() + "\":");
e.printStackTrace();
} finally {
ComThread.Release();
System.out.println("Thread \""
+ Thread.currentThread().getName() + "\" finished");
System.out.flush();
}
}
}
} }

View File

@@ -6,67 +6,195 @@ 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]); /**
*
*/
public void testIntSafeArray() {
int sourceData[] = new int[] { 100000, 200000, 300000 };
SafeArray saUnderTest = new SafeArray(Variant.VariantVariant, 3);
saUnderTest.fromIntArray(sourceData);
int[] extractedFromSafeArray = saUnderTest.toIntArray();
for (int i = 0; i < extractedFromSafeArray.length; i++) {
assertEquals("" + i, sourceData[i], extractedFromSafeArray[i]);
} }
sa.fromDoubleArray(new double[] { 1.5, 2.5, 3.5 }); assertEquals("single get failed: ", sourceData[2], saUnderTest
System.out.println("sa double=" + sa); .getInt(2));
sa.fromFloatArray(new float[] { 1.5F, 2.5F, 3.5F });
System.out.println("sa float=" + sa);
sa.fromBooleanArray(new boolean[] { true, false, true, false });
System.out.println("sa bool=" + sa);
av = sa.toVariantArray();
for (int i = 0; i < av.length; i++) {
System.out.println("toVariant=" + av[i]);
}
sa.fromCharArray(new char[] { 'a', 'b', 'c', 'd' });
System.out.println("sa char=" + sa);
sa.fromStringArray(new String[] { "hello", "from", "java", "com" });
System.out.println("sa string=" + sa);
av = sa.toVariantArray();
for (int i = 0; i < av.length; i++) {
System.out.println("toVariant=" + av[i]);
}
sa.fromVariantArray(new Variant[] {
new Variant(1), new Variant(2.3), new Variant("hi") });
System.out.println("sa variant=" + sa);
} }
/**
*
*/
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

@@ -267,7 +267,7 @@ public class SafeArrayContents extends BaseTestCase {
fail("Failed to catch expected exception"); fail("Failed to catch expected exception");
} catch (ComFailException cfe) { } catch (ComFailException cfe) {
// do nothing // do nothing
//cfe.printStackTrace(); // cfe.printStackTrace();
} }
} }
} }

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 {
@@ -36,7 +39,7 @@ public class SafeArrayDispatchTest extends BaseTestCase {
assertTrue(result.toString().equals("6")); assertTrue(result.toString().equals("6"));
} catch (ComException e) { } catch (ComException e) {
e.printStackTrace(); e.printStackTrace();
fail("script failure "+e); fail("script failure " + e);
} }
} }
} }

View File

@@ -3,191 +3,175 @@ 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 {
/** /**
* ---------------------------------------------------------------------------------------------------------------------------- * ----------------------------------------------------------------------------------------------------------------------------
* *
* ---------------------------------------------------------------------------------------------------------------------------- * ----------------------------------------------------------------------------------------------------------------------------
*/ */
public void testLeakWithSetString() { public void testLeakWithSetString() {
ActiveXComponent xl = null; ActiveXComponent xl = null;
Dispatch workbooks = null; Dispatch workbooks = null;
Dispatch workbook = null; Dispatch workbook = null;
Dispatch workSheets = null; Dispatch workSheets = null;
Dispatch sheet = null; Dispatch sheet = null;
Dispatch tabCells = null; Dispatch tabCells = null;
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
String position = "A7:DM8934"; String position = "A7:DM8934";
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();
workbook = Dispatch.get(workbooks,"Add").toDispatch(); workbook = Dispatch.get(workbooks, "Add").toDispatch();
workSheets = Dispatch.get(workbook, "Worksheets").toDispatch(); workSheets = Dispatch.get(workbook, "Worksheets").toDispatch();
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);
System.out.println("Ub0=" + sa.getUBound(1)); // nbCol System.out.println("Ub0=" + sa.getUBound(1)); // nbCol
System.out.println("Ub1=" + sa.getUBound(2)); // nbLgn System.out.println("Ub1=" + sa.getUBound(2)); // nbLgn
// number of rows // number of rows
int nbLgn = sa.getUBound(2); int nbLgn = sa.getUBound(2);
// number of columns // number of columns
int nbCol = sa.getUBound(1); int nbCol = sa.getUBound(1);
int[] colLgn = new int[] { 0, 0 }; int[] colLgn = new int[] { 0, 0 };
// now set a value on every cell in the range we retrieved // now set a value on every cell in the range we retrieved
for(int i = 1; i <= nbLgn; i++) { for (int i = 1; i <= nbLgn; i++) {
colLgn[1] = i; colLgn[1] = i;
for(int j = 1; j <= nbCol; j++) { for (int j = 1; j <= nbCol; j++) {
colLgn[0] = j; colLgn[0] = j;
// this one works with out a leak 1.13-M3 // this one works with out a leak 1.13-M3
//sa.setString(j, i, "test"); // sa.setString(j, i, "test");
// This one leaks with 1.13-M3 and earlier // This one leaks with 1.13-M3 and earlier
sa.setString(colLgn, "test"); sa.setString(colLgn, "test");
} }
} }
Dispatch.put(tabCells, "Value", sa); Dispatch.put(tabCells, "Value", sa);
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) {
try {
if (sa != null) { sa.safeRelease();
try { } catch (Exception e) {
sa.safeRelease(); e.printStackTrace();
} } finally {
catch(Exception e) { sa = null;
e.printStackTrace(); }
}
finally {
sa = null;
}
} }
if (tabCells != null) { if (tabCells != null) {
try { try {
tabCells.safeRelease(); tabCells.safeRelease();
} } catch (Exception e) {
catch(Exception e) { e.printStackTrace();
e.printStackTrace(); } finally {
} tabCells = null;
finally { }
tabCells = null;
}
}
if (sheet != null) {
try {
sheet.safeRelease();
}
catch(Exception e) {
e.printStackTrace();
}
finally {
sheet = null;
}
}
if (workSheets != null) {
try {
workSheets.safeRelease();
}
catch(Exception e) {
e.printStackTrace();
}
finally {
workSheets = null;
}
} }
if (sheet != null) {
try {
sheet.safeRelease();
} catch (Exception e) {
e.printStackTrace();
} finally {
sheet = null;
}
}
if (workSheets != null) {
try {
workSheets.safeRelease();
} catch (Exception e) {
e.printStackTrace();
} finally {
workSheets = null;
}
}
if (workbook != null) { if (workbook != null) {
try { try {
workbook.safeRelease(); workbook.safeRelease();
} } catch (Exception e) {
catch(Exception e) { e.printStackTrace();
e.printStackTrace(); } finally {
} workbook = null;
finally { }
workbook = null; }
}
} if (workbooks != null) {
try {
if (workbooks != null) { workbooks.safeRelease();
try { } catch (Exception e) {
workbooks.safeRelease(); e.printStackTrace();
} } finally {
catch(Exception e) { workbooks = null;
e.printStackTrace(); }
} }
finally {
workbooks = null; if (xl != null) {
} try {
} xl.invoke("Quit", new Variant[] {});
} catch (Exception e) {
if (xl != null) { e.printStackTrace();
try { }
xl.invoke("Quit", new Variant[] {});
} try {
catch(Exception e) { xl.safeRelease();
e.printStackTrace(); } catch (Exception e) {
} e.printStackTrace();
} finally {
try { xl = null;
xl.safeRelease(); }
} }
catch(Exception e) {
e.printStackTrace(); ComThread.Release();
} }
finally { }
xl = null;
}
}
ComThread.Release();
}
}
} }
} }

View File

@@ -7,111 +7,83 @@ 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
* <p> * options.
* SF 1085370
In my understatnding, an instance of SafeArray java
class has a
value of a pointer to VARIANT structure that contains a
pointer to
a SAFEARRAY strucuture.
On the other hand, we can create a Variant object from
the
SafeArray object 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 same SAFEARRAY structure.
In this case, the val object has a pointer to another
VARIANT that
contains a pointer to the same SAFEARRAY like this:
+-----------+
|SafeArray | +------------+
| m_pV--->VARIANT(a) |
+-----------+ | VT_ARRAY| +---------+
| parray---->SAFEARRAY|
+------------+ +^--------+
|
+-----------+ |
|Variant | +------------+ |
| m_pVariant--->VARIANT(b) | |
+-----------+ | VT_ARRAY| |
| parray-----+
+------------+
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). * SF 1085370 In my understatnding, an instance of SafeArray java class has a
* Look in the docs area at the Jacob usage document for command line options. * value of a pointer to VARIANT structure that contains a pointer to a
* SAFEARRAY strucuture.
*
* On the other hand, we can create a Variant object from the SafeArray object
* 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
* same SAFEARRAY structure.
*
* In this case, the val object has a pointer to another VARIANT that contains a
* pointer to the same SAFEARRAY like this:
*
* +-----------+ |SafeArray | +------------+ | m_pV--->VARIANT(a) |
* +-----------+ | VT_ARRAY| +---------+ | parray---->SAFEARRAY| +------------+
* +^--------+ | +-----------+ | |Variant | +------------+ | |
* m_pVariant--->VARIANT(b) | | +-----------+ | VT_ARRAY| | | parray-----+
* +------------+
*
* 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>
* 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.
*/ */
public class SafeArrayReleaseTest extends BaseTestCase { public class SafeArrayReleaseTest extends BaseTestCase {
final static int MAX = 300; final static int MAX = 300;
public void testSaveArrayRelease() {
int count; /**
System.out.println("Starting test for max = "+MAX); * verifies the release works on SafeArray
for(count = 1; count<MAX; count++) */
{ public void testSaveArrayRelease() {
int i = 0; int count;
try System.out.println("Starting test for max = " + MAX);
{ for (count = 1; count < MAX; count++) {
ComThread.InitMTA(); int i = 0;
for (i = 0; i < count; i++) try {
{ ComThread.InitMTA();
SafeArray a1 = new SafeArray(Variant.VariantVariant, 2); for (i = 0; i < count; i++) {
a1.setVariant(0, new Variant("foo")); SafeArray a1 = new SafeArray(Variant.VariantVariant, 2);
a1.setVariant(1, new Variant("bar")); a1.setVariant(0, new Variant("foo"));
Variant v = new Variant(a1); a1.setVariant(1, new Variant("bar"));
SafeArray a2 = v.toSafeArray(true); Variant v = new Variant(a1);
if (a2 == null){ SafeArray a2 = v.toSafeArray(true);
System.out.println("got null back from toSafeArray()"); if (a2 == null) {
} System.out.println("got null back from toSafeArray()");
} }
ComThread.Release(); }
System.gc(); ComThread.Release();
//System.out.print("."); System.gc();
} // 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 = "
System.out.println("\nTest ends with count = " + count + " (max = "+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,8 +31,9 @@ public class SafeArrayViaExcel extends BaseTestCase {
Dispatch workbook = Dispatch.call( Dispatch workbook = Dispatch.call(
workbooks, workbooks,
"Open", "Open",
getWindowsFilePathToPackageResource("SafeArrayViaExcel.xls",this.getClass())) getWindowsFilePathToPackageResource(
.toDispatch(); "SafeArrayViaExcel.xls", this.getClass()))
.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();
cell = Dispatch.invoke(sheet, "Range", Dispatch.Get, cell = Dispatch.invoke(sheet, "Range", Dispatch.Get,
@@ -61,7 +67,7 @@ public class SafeArrayViaExcel extends BaseTestCase {
System.out.println("Closed File\n"); System.out.println("Closed File\n");
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
fail("Caught Exception "+e); fail("Caught Exception " + e);
} finally { } finally {
xl.invoke("Quit", new Variant[] {}); xl.invoke("Quit", new Variant[] {});
} }

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 {
@@ -31,8 +38,8 @@ public class ScriptTest2 extends BaseTestCase {
ComThread.InitSTA(); ComThread.InitSTA();
ScriptTestSTA script = new ScriptTestSTA(); ScriptTestSTA script = new ScriptTestSTA();
try { try {
Thread.sleep(1000); Thread.sleep(1000);
} catch (InterruptedException ie){ } catch (InterruptedException ie) {
// should we get this? // should we get this?
} }
@@ -50,7 +57,7 @@ public class ScriptTest2 extends BaseTestCase {
System.out.println("called quit"); System.out.println("called quit");
} catch (ComException e) { } catch (ComException e) {
e.printStackTrace(); e.printStackTrace();
fail("caught exception"+e); fail("caught exception" + e);
} finally { } finally {
Integer I = null; Integer I = null;
for (int i = 1; i < 1000000; i++) { for (int i = 1; i < 1000000; i++) {
@@ -63,11 +70,11 @@ public class ScriptTest2 extends BaseTestCase {
public class ScriptTestSTA extends STA { public class ScriptTestSTA extends STA {
public DispatchEvents de = null; public DispatchEvents de = null;
public Dispatch sControl = null; public Dispatch sControl = null;
public DispatchProxy sCon = null; public DispatchProxy sCon = null;
public boolean OnInit() { public boolean OnInit() {
try { try {

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;
@@ -42,9 +43,9 @@ public class ScriptTest2ActiveX extends BaseTestCase {
ScriptTest2ActiveXSTA script = new ScriptTest2ActiveXSTA(); ScriptTest2ActiveXSTA script = new ScriptTest2ActiveXSTA();
try { try {
Thread.sleep(1000); Thread.sleep(1000);
} catch (InterruptedException ie){ } catch (InterruptedException ie) {
// should we get this? // should we get this?
} }
// get a thread-local Dispatch from sCon // get a thread-local Dispatch from sCon
ActiveXComponent sc = new ActiveXComponent(sCon.toDispatch()); ActiveXComponent sc = new ActiveXComponent(sCon.toDispatch());
@@ -60,7 +61,7 @@ public class ScriptTest2ActiveX extends BaseTestCase {
System.out.println("called quit"); System.out.println("called quit");
} catch (ComException e) { } catch (ComException e) {
e.printStackTrace(); e.printStackTrace();
fail("blew up with Com Exception "+e); fail("blew up with Com Exception " + e);
} finally { } finally {
Integer I = null; Integer I = null;
for (int i = 1; i < 1000000; i++) { for (int i = 1; i < 1000000; i++) {

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 {
@@ -29,13 +34,15 @@ public class ScriptTest3 extends BaseTestCase {
ScriptTest3Inner script = new ScriptTest3Inner(); ScriptTest3Inner script = new ScriptTest3Inner();
script.start(); script.start();
try { try {
Thread.sleep(1000); Thread.sleep(1000);
} catch (InterruptedException ie){ } catch (InterruptedException ie) {
// 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,52 +1,53 @@
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
* options. * options.
*/ */
public class ScriptTestActiveX extends BaseTestCase { public class ScriptTestActiveX extends BaseTestCase {
public void testActiveXScript() { public void testActiveXScript() {
ComThread.InitSTA(true); ComThread.InitSTA(true);
DispatchEvents de = null; DispatchEvents de = null;
try { try {
String lang = "VBScript"; String lang = "VBScript";
ActiveXComponent sC = new ActiveXComponent("ScriptControl"); ActiveXComponent sC = new ActiveXComponent("ScriptControl");
sC.setProperty("Language",lang); sC.setProperty("Language", lang);
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; }
result = sC.invoke("Eval",getSampleVPScriptForEval()); Variant result;
// call it twice to see the objects reused result = sC.invoke("Eval", getSampleVPScriptForEval());
result = sC.invoke("Eval",getSampleVPScriptForEval()); // call it twice to see the objects reused
// call it 3 times to see the objects reused result = sC.invoke("Eval", getSampleVPScriptForEval());
result = sC.invoke("Eval",getSampleVPScriptForEval()); // call it 3 times to see the objects reused
System.out.println("eval("+getSampleVPScriptForEval()+") = "+ result); result = sC.invoke("Eval", getSampleVPScriptForEval());
} catch (ComException e) { System.out.println("eval(" + getSampleVPScriptForEval() + ") = "
e.printStackTrace(); + result);
} } catch (ComException e) {
finally e.printStackTrace();
{ } 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);
ComThread.Release(); ComThread.Release();
ComThread.quitMainSTA(); ComThread.quitMainSTA();
} }
} }
} }

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 {