From df0ba33797a1e6c5d5480f163cda871468eaca22 Mon Sep 17 00:00:00 2001 From: clay_shooter Date: Sat, 2 Feb 2008 01:38:25 +0000 Subject: [PATCH] B-1_14-DEV merge back to main --- .cvsignore | 2 + build.xml | 194 +- docs/BuildingJacobFromSource.html | 7 +- docs/ReleaseNotes.html | 115 +- docs/UsingJacob.html | 118 +- jni/SafeArray.cpp | 361 +- jni/SafeArray.h | 81 + jni/Variant.cpp | 61 +- jni/Variant.h | 31 + .../JavaWebStart/DLLFromJARClassLoader.java | 105 +- .../com/jacob/samples/MathProj/MathTest.java | 62 +- samples/com/jacob/samples/access/Access.java | 223 +- samples/com/jacob/samples/ado/Command.java | 269 +- .../jacob/samples/ado/CommandTypeEnum.java | 17 +- samples/com/jacob/samples/ado/Connection.java | 250 +- samples/com/jacob/samples/ado/Field.java | 127 +- samples/com/jacob/samples/ado/Fields.java | 51 +- samples/com/jacob/samples/ado/Recordset.java | 449 +- samples/com/jacob/samples/ado/test.java | 87 +- samples/com/jacob/samples/applet/AppTest.java | 18 +- .../com/jacob/samples/atl/MultiFaceTest.java | 17 +- .../samples/office/ExcelDispatchTest.java | 78 +- .../jacob/samples/office/VisioPrintTest.java | 13 +- .../office/WordDocumentProperties.java | 240 +- .../com/jacob/samples/outlook/Outlook.java | 97 +- .../com/jacob/samples/system/DiskUtils.java | 104 +- .../jacob/samples/system/SystemMonitor.java | 28 +- samples/com/jacob/samples/visio/VisioApp.java | 172 +- .../jacob/samples/visio/VisioAppFacade.java | 250 +- .../com/jacob/samples/visio/VisioDemo.java | 310 +- .../samples/visio/VisioEventAdapter.java | 89 +- .../samples/visio/VisioEventListener.java | 34 +- .../jacob/samples/visio/VisioException.java | 21 +- src/com/jacob/activeX/ActiveXComponent.java | 1023 ++--- .../jacob/activeX/ActiveXDispatchEvents.java | 119 +- .../jacob/activeX/ActiveXInvocationProxy.java | 128 +- src/com/jacob/com/ComException.java | 203 +- src/com/jacob/com/ComFailException.java | 99 +- src/com/jacob/com/ComThread.java | 245 +- src/com/jacob/com/Currency.java | 91 + src/com/jacob/com/DateUtilities.java | 44 +- src/com/jacob/com/Dispatch.java | 2627 ++++++----- src/com/jacob/com/DispatchEvents.java | 315 +- src/com/jacob/com/DispatchIdentifier.java | 82 + src/com/jacob/com/DispatchProxy.java | 102 +- src/com/jacob/com/EnumVariant.java | 223 +- src/com/jacob/com/InvocationProxy.java | 113 +- .../jacob/com/InvocationProxyAllVariants.java | 91 +- src/com/jacob/com/JacobException.java | 16 +- src/com/jacob/com/JacobObject.java | 187 +- src/com/jacob/com/JacobReleaseInfo.java | 96 + src/com/jacob/com/LibraryLoader.java | 202 +- src/com/jacob/com/MainSTA.java | 8 +- .../jacob/com/NotImplementedException.java | 20 +- src/com/jacob/com/ROT.java | 214 +- src/com/jacob/com/STA.java | 127 +- src/com/jacob/com/SafeArray.java | 1977 +++++---- src/com/jacob/com/Variant.java | 3917 +++++++++-------- src/com/jacob/com/VariantUtilities.java | 471 ++ src/com/jacob/com/VariantViaEvent.java | 17 +- src/com/jacob/com/WrongThreadException.java | 29 +- .../com/ActiveXComponentFactoryTest.java | 104 +- unittest/com/jacob/com/DateUtilitiesTest.java | 64 +- .../com/jacob/com/DispatchNullProgramId.java | 28 +- unittest/com/jacob/com/DispatchTest.java | 24 +- .../jacob/com/DispatchValidDispatchTest.java | 51 +- unittest/com/jacob/com/JacobObjectTest.java | 20 +- unittest/com/jacob/com/LibraryLoaderTest.java | 79 + unittest/com/jacob/com/ROT2Test.java | 15 +- unittest/com/jacob/com/ROT3Test.java | 23 +- unittest/com/jacob/com/ROTTest.java | 226 +- unittest/com/jacob/com/VariantDateTest.java | 103 +- unittest/com/jacob/com/VariantTest.java | 755 ++-- .../com/jacob/com/VariantUtilitiesTest.java | 33 + unittest/com/jacob/test/BaseTestCase.java | 80 +- .../jacob/test/errors/UnicodeErrorTest.java | 20 +- .../com/jacob/test/events/ExcelEventTest.java | 120 +- unittest/com/jacob/test/events/IETest.java | 534 ++- .../jacob/test/events/IETestActiveXProxy.java | 413 +- .../com/jacob/test/events/WordEventTest.java | 63 +- .../com/jacob/test/excel/ControllerTest.java | 236 + unittest/com/jacob/test/excel/teste.xls | Bin 0 -> 15360 bytes .../jacob/test/powerpoint/PowerpointTest.java | 245 +- .../test/safearray/SafeArrayBasicTest.java | 263 +- .../test/safearray/SafeArrayContents.java | 2 +- .../test/safearray/SafeArrayDispatchTest.java | 5 +- .../jacob/test/safearray/SafeArrayLeak.java | 262 +- .../test/safearray/SafeArrayReleaseTest.java | 178 +- .../test/safearray/SafeArrayViaExcel.java | 24 +- .../com/jacob/test/vbscript/ScriptTest.java | 10 +- .../com/jacob/test/vbscript/ScriptTest2.java | 27 +- .../test/vbscript/ScriptTest2ActiveX.java | 13 +- .../com/jacob/test/vbscript/ScriptTest3.java | 28 +- .../test/vbscript/ScriptTest3ActiveX.java | 15 +- .../test/vbscript/ScriptTestActiveX.java | 73 +- .../test/vbscript/ScriptTestErrEvents.java | 19 +- .../com/jacob/test/windowsmedia/WMPlayer.java | 2 +- 97 files changed, 12208 insertions(+), 8816 deletions(-) create mode 100644 src/com/jacob/com/Currency.java create mode 100644 src/com/jacob/com/DispatchIdentifier.java create mode 100644 src/com/jacob/com/JacobReleaseInfo.java create mode 100644 src/com/jacob/com/VariantUtilities.java create mode 100644 unittest/com/jacob/com/LibraryLoaderTest.java create mode 100644 unittest/com/jacob/com/VariantUtilitiesTest.java create mode 100644 unittest/com/jacob/test/excel/ControllerTest.java create mode 100644 unittest/com/jacob/test/excel/teste.xls diff --git a/.cvsignore b/.cvsignore index b35a05a..a08c618 100644 --- a/.cvsignore +++ b/.cvsignore @@ -4,6 +4,7 @@ jacobdll.jar *.zip RELEASE.txt .project +.cproject .classpath compilation_tools.properties version.properties @@ -13,3 +14,4 @@ release foo.foo foo.ser +JacobVersion.properties diff --git a/build.xml b/build.xml index 69e07a5..31c94c4 100644 --- a/build.xml +++ b/build.xml @@ -16,15 +16,15 @@ 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: - JDK=d:\\j2sdk1.4.2_14 + JDK=d:\\jdk1.5.0_11 MSDEV_DIR=d:\\apps\\Microsoft Visual Studio 8\\VC 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 values are specific to YOUR environment. - The version.properties file is now completely autogenerated + The JacobVersion.properties file is now completely autogenerated ====================================================================== --> @@ -47,17 +47,19 @@ Now build up all the derived properties ================================================================== --> - - - - - - - + + + + + + + + + - + @@ -66,13 +68,14 @@ - + - - - + + + + @@ -87,13 +90,13 @@ - - - - - - - + + + + + + + + - + - + - + - - - - + + + + - + - - + + + - + - + - + - + - + - + - + - + - + + depends="javaJarBin,makeDll.x86,makeDll.x64"> @@ -189,7 +194,7 @@ - + @@ -199,38 +204,38 @@ ================================================================== --> - + Building Jacob classes in ${release.dir.java} - + listfiles="true" debug="on" source="1.5" /> Building sample classes in ${release.dir.java} + listfiles="true" debug="on" source="1.5" /> Building Jacob test classes in ${release.dir.java} using junit jar ${junit.jar} - + listfiles="true" debug="on" source="1.5" /> + Removing old jars Packaging java classes... + Version File is ${release.dir.java.meta.inf}/${generated.filename.version} - - Clean up the (x86) target folders and file, for safety + + Clean up the (X86) target folders and file, for safety - Compiling (x86) C++ classes with JDK JNI library ${JDK} + Compiling (X86) C++ classes with JDK JNI library ${JDK} @@ -294,11 +300,11 @@ - - Clean up the (AMD64) target folders and file, for safety - - Compiling C++ (AMD64) classes with JDK JNI library ${JDK} - + + Clean up the (x64) target folders and file, for safety + + Compiling C++ (x64) classes with JDK JNI library ${JDK} + @@ -334,7 +340,7 @@ 32 bit target Yes No 64 bit target Yes Yes ================================================================== --> - + Clean up the target folders and file, for safety Using ${library.x86} @@ -361,40 +367,40 @@ - + Clean up the target folders and file, for safety - - Creating {$release.file.AMD64.dll} - + + Creating {$release.file.x64.dll} + - + - - - - + + + + - + - + - + - + ${application.title}]]> ${application.vendor}]]> - - - - - + + + + + @@ -416,7 +422,7 @@ Use this target to package all the files for a release ================================================================== --> + depends="makeDll.x86,makeDll.x64,javaJarBin,generateJavaDoc"> Packaging release... ${release.file.jar} - - - - - - + + + + + + @@ -447,14 +453,14 @@ - + diff --git a/docs/BuildingJacobFromSource.html b/docs/BuildingJacobFromSource.html index f5004a5..5b69540 100644 --- a/docs/BuildingJacobFromSource.html +++ b/docs/BuildingJacobFromSource.html @@ -34,20 +34,20 @@ been removed.

Development Environment

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 compilation_tools.properties using the example build.xml as a template.
  • Microsoft Visual C++ 8.0 and it's included library. (to D:\apps in my case)
  • Eclipse 3.3 or later from www.eclipse.org as the Java IDE.
  • Eclipse 3.3 or later with the C/C++ plugin can be used for C coding in place of VC++ IDE. -
  • Java JDK 1.4 (1.12 was built using 1.4.2.13) Compilation using JDK 1.5 has not been tested +
  • Java JDK 1.5 (1.14 was built using 1.5.0.11)

- + @@ -55,6 +55,7 @@ using the example build.xml as a template. +
ReleaseC VersionJava VersionANT VersionEclipse Version Usedgenerated DLLs
up to 1.6VC 98 (6.0)?Used MAKE?32 bit
up to 1.6VC 98 (6.0)?MAKE?32 bit
1.7VC 98 (6.0)1.41.??32 bit
1.8VC 98 (6.0)1.41.??32 bit
1.9VC 98 (6.0)1.41.??32 bit
1.11VC 98 (6.0) & 2003 64bit libs1.4.?1.6.?3.2.132 and 64 bit
1.12VC 98 (6.0) & 2003 64bit libs1.4.21.6.53.2.232 and 64 bit
1.13VC 20051.4.21.7.03.332 and 64 bit
1.14VC 20051.5.01.7.03.332 and 64 bit
Microsoft Visual C++ 8.0 supports 64 bit builds. so no additional tools are required. diff --git a/docs/ReleaseNotes.html b/docs/ReleaseNotes.html index cae4d40..f2ebdd1 100644 --- a/docs/ReleaseNotes.html +++ b/docs/ReleaseNotes.html @@ -1,5 +1,113 @@ + +

JACOB 1.14

+

What's New

+
    +
  • + Binaries are now compiled with Java 5. JDK 1.4 support dropped. +
  • +
  • + Jacob now loads dlls based on platform (32 bit /64 bit) and version number. +
  • +
+ +

Tracked Changes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Bugs
1857439(M7) version.properties renamed to META-INF/JacobVersion.properties + to remove collision with WebSphere version.properties.
1840487(M6) toJavaObject() converting to SafeArray + did shallow copy that left two objects pointing at the same windows memory.
1829201(M5) DECIMAL rounding behavior externalized + and old Variant decimal API restored.
1829201(M5) DECIMAL rounding behavior externalized + and old Variant decimal API restored.
1829201(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
1815163(M2) Double and Decimal conversion to Int fails for negative values
  
Patches
  
Feature Requests
1845039 (M7) Jacob DLL name can now be customized to + support bundling of Jacob in other products.
1845039 (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
1828371 (M4) Added VT_I8 support to SafeArray.
1813458(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.
1816863(M1) Migrate Jacob to JDK 5
  
Known Issues
This is now built with Java 5 compiler and + Java 5 syntax. This release is not compatible with JDK 1.4.x and earlier.
This release requires the Visual C++ 2005 + libraries. See 1.13 Known Issues for more information.
+

JACOB 1.13

What's New

@@ -82,11 +190,14 @@ Known Issues - VC++ libraries + Jacob 1.13 is built using VC++ 2005. 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 - installed on older systems. It can be obtained from the MS downloads site. + 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. diff --git a/docs/UsingJacob.html b/docs/UsingJacob.html index 8ad203c..435470c 100644 --- a/docs/UsingJacob.html +++ b/docs/UsingJacob.html @@ -23,6 +23,16 @@ to provide a more object like API. The only exception to this guideline is that the ActiveXComponent class is always used to make the initial connection to the target dll/COM component. + +
+

Considerations when doing server side automation of office

+

+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 + +support note +on the Microsoft web site that discusses some of the issues. +


Determining the API of the target application

@@ -32,14 +42,22 @@ Section not yet written.

The Jacob DLL

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 -add jacob.dll directory to the path. +This means that you must either copy the appropriate jacob ddll into your path or +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:
+jacob<platform>.<version.>.dll

+

Classloader issues

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 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. -

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. 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 -

+


Jacob Command Line Settings

-This library supports several different : -

java.library.path

- Used to add the location of the jacob dll to the JVM's library path. +This library supports several differentommand line options: + + + -

com.jacob.autogc

+ + + + + + + + -

com.jacob.debug

+ + -

-XCheck:jni

+ +
+

dll path location and dll name customization

+
    +

java.library.path

+
+ Standard Java property used to add the location of the jacob dll to the JVM's library path. + (Added 1.11)

- Example: -Djava.library.path=d:/jacob/release/x86 + Example: -Djava.library.path=d:/jacob/release/x86 +

    +

jacob.dll.name

+
+ 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) +

+ Example: -Djacob.dll.name=MyFunkyDllName.dll +

    +

jacob.dll.name.x86 & jacob.dll.name.x64

+
+ 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) +

+ Example to override 32 bit dll name: -Djacob.dll.name.x86=MyFunkyDllName-32bit.dll +

+

Memory Management

+
    +

com.jacob.autogc

+
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 com.java.autogc 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. Code was added to let users try and let the JVM manage the object life cycles even though the JacobComLifetime.html document - says this is a bad idea. + says this is a bad idea. Added 1.9.

This value is cached at startup and cannot be changed on-the-fly via System.setProperty();

- The default value is false + The default value is false

Example: -Dcom.jacob.autogc=false -

<class_name>.PutInROT

+
    +

<class_name>.PutInROT

+
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 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 situations where this great reduces the long running memory footprint of applications that process a lot of events. This function is still experimental. - The functionality of this overlaps the experimental com.jacob.autogc introduced + The functionality was added 1.13. Some of this overlaps the experimental com.jacob.autogc introduced in 1.9. See the ROT.java test program for an example of the effects of this option.

@@ -126,8 +186,14 @@ This library supports several different : Example: System.setProperty("com.jacob.com.VariantViaVariant.PutInROT","false");
Example: -Dcom.jacob.com.VariantViaVariant.PutInROT=false +

+

Debugging and Troubleshooting

+
    +

com.jacob.debug

+
Determines if debug output is enabled to standard out.

This value is cached at startup and cannot be changed on-the-fly via System.setProperty(); @@ -136,14 +202,21 @@ This library supports several different :

Example: -Dcom.jacob.debug=false +

    + +

-XCheck:jni

+
This turns on additional JVM checking for JNI issues. This is not an actual JACOB system property but a property used by the JVM.

The default is "no additional checking" - Example: -XCheck:jni -

+ Example: -XCheck:jni +

+ +


Finding the DLL version using windows command line

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 The Microsoft msdn web site +
+

Unit Tests

+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: +
-Djava.library.path=d:/jacob_1_5/release/x86 . +

-Last Modified 7/2007 +Last Modified 12/2007 \ No newline at end of file diff --git a/jni/SafeArray.cpp b/jni/SafeArray.cpp index ee96c0a..ccb92ea 100644 --- a/jni/SafeArray.cpp +++ b/jni/SafeArray.cpp @@ -384,25 +384,25 @@ JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromCharArray len = numElements(psa); } // 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) { VARIANT v; VariantInit(&v); V_VT(&v) = VT_UI2; for(int i=0;iReleaseCharArrayElements(a, iarr, 0); + env->ReleaseCharArrayElements(a, arrayElements, 0); } /* @@ -427,25 +427,68 @@ JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromIntArray len = numElements(psa); } // 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) { VARIANT v; VariantInit(&v); V_VT(&v) = VT_I4; for(int i=0;iReleaseIntArrayElements(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;iReleaseLongArrayElements(a, arrayElements, 0); } /* @@ -470,25 +513,25 @@ JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromShortArray len = numElements(psa); } // 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) { VARIANT v; VariantInit(&v); V_VT(&v) = VT_I2; for(int i=0;iReleaseShortArrayElements(a, iarr, 0); + env->ReleaseShortArrayElements(a, arrayElements, 0); } /* @@ -513,25 +556,25 @@ JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromDoubleArray len = numElements(psa); } // 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) { VARIANT v; VariantInit(&v); V_VT(&v) = VT_R8; for(int i=0;iReleaseDoubleArrayElements(a, iarr, 0); + env->ReleaseDoubleArrayElements(a, arrayElements, 0); } /* @@ -613,25 +656,25 @@ JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromByteArray len = numElements(psa); } // 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) { VARIANT v; VariantInit(&v); V_VT(&v) = VT_UI1; for(int i=0;iReleaseByteArrayElements(a, iarr, 0); + env->ReleaseByteArrayElements(a, arrayElements, 0); } /* @@ -656,25 +699,25 @@ JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromFloatArray len = numElements(psa); } // 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) { VARIANT v; VariantInit(&v); V_VT(&v) = VT_R4; for(int i=0;iReleaseFloatArrayElements(a, iarr, 0); + env->ReleaseFloatArrayElements(a, arrayElements, 0); } /* @@ -699,13 +742,13 @@ JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromBooleanArray len = numElements(psa); } // 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) { VARIANT v; VariantInit(&v); V_VT(&v) = VT_BOOL; for(int i=0;iReleaseBooleanArrayElements(a, iarr, 0); + env->ReleaseBooleanArrayElements(a, arrayElements, 0); } /* @@ -776,14 +819,14 @@ JNIEXPORT jcharArray JNICALL Java_com_jacob_com_SafeArray_toCharArray VARTYPE vt; SafeArrayGetVartype(sa, &vt); if (vt == VT_UI2 || vt == VT_I2) { - jcharArray iarr = env->NewCharArray(num); + jcharArray arrayElements = env->NewCharArray(num); void *pData; SafeArrayAccessData(sa, &pData); - env->SetCharArrayRegion(iarr, 0, num, (jchar *)pData); + env->SetCharArrayRegion(arrayElements, 0, num, (jchar *)pData); SafeArrayUnaccessData(sa); - return iarr; + return arrayElements; } else if (vt == VT_VARIANT) { - jcharArray iarr = env->NewCharArray(num); + jcharArray arrayElements = env->NewCharArray(num); VARIANT v; VariantInit(&v); for(int i=lb;i<=ub;i++) { @@ -793,9 +836,9 @@ JNIEXPORT jcharArray JNICALL Java_com_jacob_com_SafeArray_toCharArray return NULL; } jchar val = V_UI2(&v); - env->SetCharArrayRegion(iarr, i, 1, &val); + env->SetCharArrayRegion(arrayElements, i, 1, &val); } - return iarr; + return arrayElements; } return NULL; } @@ -820,14 +863,14 @@ JNIEXPORT jintArray JNICALL Java_com_jacob_com_SafeArray_toIntArray VARTYPE vt; SafeArrayGetVartype(sa, &vt); if (vt == VT_I4) { - jintArray iarr = env->NewIntArray(num); + jintArray arrayElements = env->NewIntArray(num); void *pData; SafeArrayAccessData(sa, &pData); - env->SetIntArrayRegion(iarr, 0, num, (jint *)pData); + env->SetIntArrayRegion(arrayElements, 0, num, (jint *)pData); SafeArrayUnaccessData(sa); - return iarr; + return arrayElements; } else if (vt == VT_VARIANT) { - jintArray iarr = env->NewIntArray(num); + jintArray arrayElements = env->NewIntArray(num); VARIANT v; VariantInit(&v); for(int i=lb;i<=ub;i++) { @@ -837,9 +880,54 @@ JNIEXPORT jintArray JNICALL Java_com_jacob_com_SafeArray_toIntArray return NULL; } 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; } @@ -865,14 +953,14 @@ JNIEXPORT jshortArray JNICALL Java_com_jacob_com_SafeArray_toShortArray VARTYPE vt; SafeArrayGetVartype(sa, &vt); if (vt == VT_I2) { - jshortArray iarr = env->NewShortArray(num); + jshortArray arrayElements = env->NewShortArray(num); void *pData; SafeArrayAccessData(sa, &pData); - env->SetShortArrayRegion(iarr, 0, num, (jshort *)pData); + env->SetShortArrayRegion(arrayElements, 0, num, (jshort *)pData); SafeArrayUnaccessData(sa); - return iarr; + return arrayElements; } else if (vt == VT_VARIANT) { - jshortArray iarr = env->NewShortArray(num); + jshortArray arrayElements = env->NewShortArray(num); VARIANT v; VariantInit(&v); for(int i=lb;i<=ub;i++) { @@ -882,9 +970,9 @@ JNIEXPORT jshortArray JNICALL Java_com_jacob_com_SafeArray_toShortArray return NULL; } jshort val = V_I2(&v); - env->SetShortArrayRegion(iarr, i, 1, &val); + env->SetShortArrayRegion(arrayElements, i, 1, &val); } - return iarr; + return arrayElements; } return NULL; } @@ -909,14 +997,14 @@ JNIEXPORT jdoubleArray JNICALL Java_com_jacob_com_SafeArray_toDoubleArray VARTYPE vt; SafeArrayGetVartype(sa, &vt); if (vt == VT_R8) { - jdoubleArray iarr = env->NewDoubleArray(num); + jdoubleArray arrayElements = env->NewDoubleArray(num); void *pData; SafeArrayAccessData(sa, &pData); - env->SetDoubleArrayRegion(iarr, 0, num, (jdouble *)pData); + env->SetDoubleArrayRegion(arrayElements, 0, num, (jdouble *)pData); SafeArrayUnaccessData(sa); - return iarr; + return arrayElements; } else if (vt == VT_VARIANT) { - jdoubleArray iarr = env->NewDoubleArray(num); + jdoubleArray arrayElements = env->NewDoubleArray(num); VARIANT v; VariantInit(&v); for(int i=lb;i<=ub;i++) { @@ -926,9 +1014,9 @@ JNIEXPORT jdoubleArray JNICALL Java_com_jacob_com_SafeArray_toDoubleArray return NULL; } jdouble val = V_R8(&v); - env->SetDoubleArrayRegion(iarr, i, 1, &val); + env->SetDoubleArrayRegion(arrayElements, i, 1, &val); } - return iarr; + return arrayElements; } return NULL; } @@ -955,7 +1043,7 @@ JNIEXPORT jobjectArray JNICALL Java_com_jacob_com_SafeArray_toStringArray if (vt == VT_VARIANT) { jclass sClass = env->FindClass("java/lang/String"); - jobjectArray iarr = env->NewObjectArray(num, sClass, NULL); + jobjectArray arrayElements = env->NewObjectArray(num, sClass, NULL); VARIANT v; VariantInit(&v); 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); 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) { 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++) { BSTR bs = NULL; long ix = i; SafeArrayGetElement(sa, &ix, (void*) &bs); 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); return NULL; @@ -1005,14 +1093,14 @@ JNIEXPORT jbyteArray JNICALL Java_com_jacob_com_SafeArray_toByteArray VARTYPE vt; SafeArrayGetVartype(sa, &vt); if (vt == VT_I1 || vt == VT_UI1) { - jbyteArray iarr = env->NewByteArray(num); + jbyteArray arrayElements = env->NewByteArray(num); jbyte *pData; SafeArrayAccessData(sa, (void **)&pData); - env->SetByteArrayRegion(iarr, 0, num, pData); + env->SetByteArrayRegion(arrayElements, 0, num, pData); SafeArrayUnaccessData(sa); - return iarr; + return arrayElements; } else if (vt == VT_VARIANT) { - jbyteArray iarr = env->NewByteArray(num); + jbyteArray arrayElements = env->NewByteArray(num); VARIANT v; VariantInit(&v); 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; } jbyte val = V_UI1(&v); - env->SetByteArrayRegion(iarr, j, 1, &val); + env->SetByteArrayRegion(arrayElements, j, 1, &val); } - return iarr; + return arrayElements; } return NULL; } @@ -1049,14 +1137,14 @@ JNIEXPORT jfloatArray JNICALL Java_com_jacob_com_SafeArray_toFloatArray VARTYPE vt; SafeArrayGetVartype(sa, &vt); if (vt == VT_R4) { - jfloatArray iarr = env->NewFloatArray(num); + jfloatArray arrayElements = env->NewFloatArray(num); void *pData; SafeArrayAccessData(sa, &pData); - env->SetFloatArrayRegion(iarr, 0, num, (jfloat *)pData); + env->SetFloatArrayRegion(arrayElements, 0, num, (jfloat *)pData); SafeArrayUnaccessData(sa); - return iarr; + return arrayElements; } else if (vt == VT_VARIANT) { - jfloatArray iarr = env->NewFloatArray(num); + jfloatArray arrayElements = env->NewFloatArray(num); VARIANT v; VariantInit(&v); for(int i=lb;i<=ub;i++) { @@ -1066,9 +1154,9 @@ JNIEXPORT jfloatArray JNICALL Java_com_jacob_com_SafeArray_toFloatArray return NULL; } jfloat val = V_R4(&v); - env->SetFloatArrayRegion(iarr, i, 1, &val); + env->SetFloatArrayRegion(arrayElements, i, 1, &val); } - return iarr; + return arrayElements; } return NULL; } @@ -1094,17 +1182,17 @@ JNIEXPORT jbooleanArray JNICALL Java_com_jacob_com_SafeArray_toBooleanArray SafeArrayGetVartype(sa, &vt); if (vt == VT_BOOL) { // 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; for(int i=lb,j=0;i<=ub;i++,j++) { long ix = i; SafeArrayGetElement(sa, &ix, (void*) &v); 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) { - jbooleanArray iarr = env->NewBooleanArray(num); + jbooleanArray arrayElements = env->NewBooleanArray(num); VARIANT v; VariantInit(&v); for(int i=lb;i<=ub;i++) { @@ -1114,9 +1202,9 @@ JNIEXPORT jbooleanArray JNICALL Java_com_jacob_com_SafeArray_toBooleanArray return NULL; } 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; } @@ -1310,25 +1398,25 @@ JNIEXPORT jobjectArray JNICALL Java_com_jacob_com_SafeArray_toVariantArray } \ VARTYPE vt; \ SafeArrayGetVartype(psa, &vt); \ - jtyp *iarr = env->jgetArr(ja, 0); \ + jtyp *arrayElements = env->jgetArr(ja, 0); \ if (vt == VT_VARIANT) { \ VARIANT v; \ VariantInit(&v); \ V_VT(&v) = varType; \ for(int i=ja_start,j=idx;ijrelArr(ja, iarr, 0); + env->jrelArr(ja, arrayElements, 0); /* * Class: SafeArray @@ -1398,6 +1486,8 @@ JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setChars GetCharArrayElements, ReleaseCharArrayElements); } +/*----------------------- INTS ----------------------------------*/ + /* * Class: SafeArray * Method: getInt @@ -1465,6 +1555,79 @@ JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setInts 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 * Method: getShort @@ -2206,27 +2369,27 @@ JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setBooleans { len = numElements(psa); } - jboolean *iarr = env->GetBooleanArrayElements(ja, 0); + jboolean *arrayElements = env->GetBooleanArrayElements(ja, 0); if (vt == VT_VARIANT) { VARIANT v; VariantInit(&v); V_VT(&v) = VT_BOOL; for(int i=ja_start,j=idx;iReleaseBooleanArrayElements(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); } +/*----------------------- INTS ----------------------------------*/ + /* * Class: com_jacob_com_SafeArray * Method: getInt @@ -2683,6 +2848,34 @@ JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setInt___3II 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 * Method: getShort diff --git a/jni/SafeArray.h b/jni/SafeArray.h index 7088b92..a20038e 100644 --- a/jni/SafeArray.h +++ b/jni/SafeArray.h @@ -149,6 +149,14 @@ JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromCharArray JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromIntArray (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 * Method: fromShortArray @@ -221,6 +229,14 @@ JNIEXPORT jcharArray JNICALL Java_com_jacob_com_SafeArray_toCharArray JNIEXPORT jintArray JNICALL Java_com_jacob_com_SafeArray_toIntArray (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 * Method: toShortArray @@ -373,6 +389,54 @@ JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_getInts JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setInts (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 * 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 (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 * Method: getShort diff --git a/jni/Variant.cpp b/jni/Variant.cpp index f18ca57..7f13de0 100644 --- a/jni/Variant.cpp +++ b/jni/Variant.cpp @@ -611,6 +611,17 @@ JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantCurrency } 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. * 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; } +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 (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 (JNIEnv *env, jobject _this, jint i) { @@ -801,6 +837,19 @@ JNIEXPORT jlong JNICALL Java_com_jacob_com_Variant_getVariantCurrencyRef 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 (JNIEnv *env, jobject _this) { @@ -1076,7 +1125,11 @@ JNIEXPORT jint JNICALL Java_com_jacob_com_Variant_getVariantVariant VariantClear(v); // whatever was there before DECIMAL *pd = (DECIMAL *)CoTaskMemAlloc(sizeof(DECIMAL)); 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->Mid32 = mid; pd->Lo32 = lo; @@ -1099,7 +1152,11 @@ JNIEXPORT jint JNICALL Java_com_jacob_com_Variant_getVariantVariant VariantClear(v); // whatever was there before d = (DECIMAL*)v; 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->Mid32 = mid; d->Lo32 = lo; diff --git a/jni/Variant.h b/jni/Variant.h index 439a070..1383e75 100644 --- a/jni/Variant.h +++ b/jni/Variant.h @@ -282,6 +282,14 @@ JNIEXPORT jdouble JNICALL Java_com_jacob_com_Variant_getVariantDouble JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantCurrency (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 * Method: putVariantDispatch @@ -306,6 +314,13 @@ JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantDouble JNIEXPORT jlong JNICALL Java_com_jacob_com_Variant_getVariantCurrency (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 * Method: putVariantFloatRef @@ -322,6 +337,14 @@ JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantFloatRef JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantCurrencyRef (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 * Method: putVariantErrorRef @@ -386,6 +409,14 @@ JNIEXPORT jfloat JNICALL Java_com_jacob_com_Variant_getVariantFloatRef JNIEXPORT jlong JNICALL Java_com_jacob_com_Variant_getVariantCurrencyRef (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 * Method: getVariantErrorRef diff --git a/samples/com/jacob/samples/JavaWebStart/DLLFromJARClassLoader.java b/samples/com/jacob/samples/JavaWebStart/DLLFromJARClassLoader.java index 3eed3bf..f888dc7 100644 --- a/samples/com/jacob/samples/JavaWebStart/DLLFromJARClassLoader.java +++ b/samples/com/jacob/samples/JavaWebStart/DLLFromJARClassLoader.java @@ -4,62 +4,71 @@ import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; +import com.jacob.com.LibraryLoader; + /** * 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 - * Applet (assuming security allows access to the file system). - * The obvious thing to do here is to jar up - * the Jacob.dll so that it can be downloaded the client along with the rest - * of the resources. This is simple except that the System.Load() function - * does not search jar files for DLLs. It searches the classpath. - * The work around to this problem is to write the DLL to a temporary file and then + * on the client machine. This is true in JavaWebStart (JWS) and possibly Applet + * (assuming security allows access to the file system). The obvious thing to do + * here is to jar up the Jacob.dll so that it can be downloaded the client along + * with the rest of the resources. This is simple except that the System.Load() + * function does not search jar files for DLLs. It searches the classpath. 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. * * The following code demonstrates this idea. * * @author joe - * + * */ public class DLLFromJARClassLoader { - /** - * Load the DLL from the classpath rather than from the java path. - * This code uses this class's class loader to find the dell in one - * of the jar files in this class's class path. It then - * writes the file as a temp file and calls Load() on the temp file. - * The temporary file is marked to be deleted on exit so the dll - * is deleted from the system when the application exits. - *

- * Derived from ample code found in Sun's java forums - * + * Derived from ample code found in Sun's java forums - * 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. + * 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. */ class MathTest { + /** + * standard main program to run the sample + * + * @param args + * command line parameters + */ public static void main(String[] args) { MathTest me = new MathTest(); 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 // System.runFinalizersOnExit(true); Dispatch test = new ActiveXComponent("MathTest.Math"); @@ -42,14 +55,29 @@ class MathTest { 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"); - } -} - } diff --git a/samples/com/jacob/samples/access/Access.java b/samples/com/jacob/samples/access/Access.java index 0486611..c99bb73 100644 --- a/samples/com/jacob/samples/access/Access.java +++ b/samples/com/jacob/samples/access/Access.java @@ -19,123 +19,126 @@ */ package com.jacob.samples.access; -import com.jacob.com.*; -import com.jacob.activeX.*; +import com.jacob.activeX.ActiveXComponent; +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). - * Look in the docs area at the Jacob usage document for command line options. - * + * 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. + * */ -class Access -{ - /** - * the main loop for the test - * @param args - * @throws Exception - */ - public static void main(String[] args) throws Exception - { - ComThread.InitSTA(); - // original test used this - // ActiveXComponent ax = new ActiveXComponent("DAO.PrivateDBEngine"); - // my xp box with a later release of access needed this - ActiveXComponent ax = new ActiveXComponent("DAO.PrivateDBEngine.35"); - // this only works for access files pre-access-2000 - // this line doesn't work on my xp box in Eclipse - //Dispatch db = open(ax, ".\\sample2.mdb"); - // this works when running in eclipse because the test cases run pwd project root - Dispatch db = open(ax, "samples/com/jacob/samples/access/sample2.mdb"); - String sql = "select * from MainTable"; - // make a temporary querydef - Dispatch qd = Dispatch.call(db, "CreateQueryDef","").toDispatch(); - // set the SQL string on it - Dispatch.put(qd, "SQL", sql); - Variant result = getByQueryDef(qd); +class Access { + /** + * the main loop for the test + * + * @param args + * @throws Exception + */ + public static void main(String[] args) throws Exception { + ComThread.InitSTA(); + // original test used this + // ActiveXComponent ax = new ActiveXComponent("DAO.PrivateDBEngine"); + // my xp box with a later release of access needed this + ActiveXComponent ax = new ActiveXComponent("DAO.PrivateDBEngine.35"); + // this only works for access files pre-access-2000 + // this line doesn't work on my xp box in Eclipse + // Dispatch db = open(ax, ".\\sample2.mdb"); + // this works when running in eclipse because the test cases run pwd + // project root + Dispatch db = open(ax, "samples/com/jacob/samples/access/sample2.mdb"); + String sql = "select * from MainTable"; + // make a temporary querydef + Dispatch qd = Dispatch.call(db, "CreateQueryDef", "").toDispatch(); + // set the SQL string on it + Dispatch.put(qd, "SQL", sql); + Variant result = getByQueryDef(qd); // the 2-d safearray is transposed from what you might expect - System.out.println("resulting array is "+result.toSafeArray()); - close(db); - System.out.println("about to call ComThread.Release()"); - ComThread.Release(); - } + System.out.println("resulting array is " + result.toSafeArray()); + close(db); + System.out.println("about to call ComThread.Release()"); + ComThread.Release(); + } - /** - * Open a database - * @param ax - * @param fileName - * @return dispatch object that was opened - */ - public static Dispatch open(ActiveXComponent ax, String fileName) - { - Variant f = new Variant(false); - // open the file in read-only mode - Variant[] args = new Variant[] {new Variant(fileName), f, f}; - Dispatch openDB = ax.invoke("OpenDatabase", args).toDispatch(); - return openDB; - } + /** + * Open a database + * + * @param ax + * @param fileName + * @return dispatch object that was opened + */ + public static Dispatch open(ActiveXComponent ax, String fileName) { + Variant f = new Variant(false); + // open the file in read-only mode + Variant[] args = new Variant[] { new Variant(fileName), f, f }; + Dispatch openDB = ax.invoke("OpenDatabase", args).toDispatch(); + return openDB; + } - /** - * Close a database - * @param openDB db to be closed - */ - public static void close(Dispatch openDB) - { - Dispatch.call(openDB, "Close"); - } + /** + * Close a database + * + * @param openDB + * db to be closed + */ + public static void close(Dispatch openDB) { + Dispatch.call(openDB, "Close"); + } - /** - * Extract the values from the recordset - * @param recset - * @return Variant that is the returned values - */ - public static Variant getValues(Dispatch recset) - { - Dispatch.callSub(recset,"moveFirst"); - Variant vi = new Variant(4096); - Variant v = Dispatch.call(recset,"GetRows", vi); - return v; - } + /** + * Extract the values from the recordset + * + * @param recset + * @return Variant that is the returned values + */ + public static Variant getValues(Dispatch recset) { + Dispatch.callSub(recset, "moveFirst"); + Variant vi = new Variant(4096); + Variant v = Dispatch.call(recset, "GetRows", vi); + return v; + } - /** - * should return ?? for the passed in ?? - * @param qd - * @return Variant results of query? - */ - public static Variant getByQueryDef(Dispatch qd) - { - // get a reference to the recordset - Dispatch recset = Dispatch.call(qd, "OpenRecordset").toDispatch(); - // get the values as a safe array - String[] cols = getColumns(recset); - for(int i=0;i Recordset"); - Connection c = new Connection(); - c.setConnectionString(con); - c.Open(); - Command comm = new Command(); - comm.setActiveConnection(c); - comm.setCommandType(CommandTypeEnum.adCmdText); - comm.setCommandText(query); - Recordset rs = comm.Execute(); - printRS(rs); - c.Close(); + public static void getCommand(String con, String query) { + System.out.println("Command+Connection -> Recordset"); + Connection c = new Connection(); + c.setConnectionString(con); + c.Open(); + Command comm = new Command(); + comm.setActiveConnection(c); + comm.setCommandType(CommandTypeEnum.adCmdText); + comm.setCommandText(query); + Recordset rs = comm.Execute(); + printRS(rs); + c.Close(); } - public static void main(String[] args) - { - String connectStr = "DRIVER=SQL Server;SERVER=DANADLER;UID=sa;PWD=;WSID=DANADLER;DATABASE=pubs"; - String queryStr = "select * from authors"; - getCommand(connectStr, queryStr); - getRS(connectStr, queryStr); + public static void main(String[] args) { + String connectStr = "DRIVER=SQL Server;SERVER=DANADLER;UID=sa;PWD=;WSID=DANADLER;DATABASE=pubs"; + String queryStr = "select * from authors"; + getCommand(connectStr, queryStr); + getRS(connectStr, queryStr); } } diff --git a/samples/com/jacob/samples/applet/AppTest.java b/samples/com/jacob/samples/applet/AppTest.java index c185981..ca9cc82 100644 --- a/samples/com/jacob/samples/applet/AppTest.java +++ b/samples/com/jacob/samples/applet/AppTest.java @@ -1,11 +1,15 @@ package com.jacob.samples.applet; -import java.awt.*; -import java.awt.event.*; -import java.applet.*; +import java.applet.Applet; +import java.awt.Button; +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.*; +import com.jacob.activeX.ActiveXComponent; +import com.jacob.com.Dispatch; +import com.jacob.com.Variant; /** * Applet test case @@ -38,7 +42,9 @@ public class AppTest extends Applet implements ActionListener { /** * action method that receives button actions - * @param ev the event + * + * @param ev + * the event */ public void actionPerformed(ActionEvent ev) { if (sC == null) { diff --git a/samples/com/jacob/samples/atl/MultiFaceTest.java b/samples/com/jacob/samples/atl/MultiFaceTest.java index 862860e..fc64923 100644 --- a/samples/com/jacob/samples/atl/MultiFaceTest.java +++ b/samples/com/jacob/samples/atl/MultiFaceTest.java @@ -1,14 +1,23 @@ package com.jacob.samples.atl; -import com.jacob.com.*; -import com.jacob.activeX.*; +import com.jacob.activeX.ActiveXComponent; +import com.jacob.com.Dispatch; +import com.jacob.com.Variant; class MultiFaceTest { + + /** + * standard main() test program + * + * @param args + * the command line arguments + */ public static void main(String[] args) { // this method has been deprecated as being unreliable. // shutdown should be done through other means - // whoever wrote this example should explain what this was intended to do - //System.runFinalizersOnExit(true); + // whoever wrote this example should explain what this was intended to + // do + // System.runFinalizersOnExit(true); ActiveXComponent mf = new ActiveXComponent("MultiFace.Face"); try { diff --git a/samples/com/jacob/samples/office/ExcelDispatchTest.java b/samples/com/jacob/samples/office/ExcelDispatchTest.java index 9716fce..fea6229 100644 --- a/samples/com/jacob/samples/office/ExcelDispatchTest.java +++ b/samples/com/jacob/samples/office/ExcelDispatchTest.java @@ -1,46 +1,52 @@ package com.jacob.samples.office; -import com.jacob.com.*; -import com.jacob.activeX.*; +import com.jacob.activeX.ActiveXComponent; +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. *

- * 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. + * 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 ExcelDispatchTest { - - public static void main(String[] args) - { - ComThread.InitSTA(); - - ActiveXComponent xl = new ActiveXComponent("Excel.Application"); - try { - System.out.println("version="+xl.getProperty("Version")); - System.out.println("version="+Dispatch.get(xl, "Version")); - Dispatch.put(xl, "Visible", new Variant(true)); - Dispatch workbooks = xl.getProperty("Workbooks").toDispatch(); - Dispatch workbook = Dispatch.get(workbooks,"Add").toDispatch(); - Dispatch sheet = Dispatch.get(workbook,"ActiveSheet").toDispatch(); - Dispatch a1 = Dispatch.invoke(sheet, "Range", Dispatch.Get, - new Object[] {"A1"}, - new int[1]).toDispatch(); - Dispatch a2 = Dispatch.invoke(sheet, "Range", Dispatch.Get, - new Object[] {"A2"}, - new int[1]).toDispatch(); - Dispatch.put(a1, "Value", "123.456"); - Dispatch.put(a2, "Formula", "=A1*2"); - System.out.println("a1 from excel:"+Dispatch.get(a1, "Value")); - System.out.println("a2 from excel:"+Dispatch.get(a2, "Value")); - Variant f = new Variant(false); - Dispatch.call(workbook, "Close", f); - } catch (Exception e) { - e.printStackTrace(); - } finally { - xl.invoke("Quit", new Variant[] {}); - ComThread.Release(); - } - } + + /** + * main run loop for test program + * + * @param args + * standard command line arguments + */ + public static void main(String[] args) { + ComThread.InitSTA(); + + ActiveXComponent xl = new ActiveXComponent("Excel.Application"); + try { + System.out.println("version=" + xl.getProperty("Version")); + System.out.println("version=" + Dispatch.get(xl, "Version")); + Dispatch.put(xl, "Visible", new Variant(true)); + Dispatch workbooks = xl.getProperty("Workbooks").toDispatch(); + Dispatch workbook = Dispatch.get(workbooks, "Add").toDispatch(); + Dispatch sheet = Dispatch.get(workbook, "ActiveSheet").toDispatch(); + Dispatch a1 = Dispatch.invoke(sheet, "Range", Dispatch.Get, + new Object[] { "A1" }, new int[1]).toDispatch(); + Dispatch a2 = Dispatch.invoke(sheet, "Range", Dispatch.Get, + new Object[] { "A2" }, new int[1]).toDispatch(); + Dispatch.put(a1, "Value", "123.456"); + Dispatch.put(a2, "Formula", "=A1*2"); + System.out.println("a1 from excel:" + Dispatch.get(a1, "Value")); + System.out.println("a2 from excel:" + Dispatch.get(a2, "Value")); + Variant f = new Variant(false); + Dispatch.call(workbook, "Close", f); + } catch (Exception e) { + e.printStackTrace(); + } finally { + xl.invoke("Quit", new Variant[] {}); + ComThread.Release(); + } + } } diff --git a/samples/com/jacob/samples/office/VisioPrintTest.java b/samples/com/jacob/samples/office/VisioPrintTest.java index d47cb08..94c0b00 100644 --- a/samples/com/jacob/samples/office/VisioPrintTest.java +++ b/samples/com/jacob/samples/office/VisioPrintTest.java @@ -7,8 +7,7 @@ import com.jacob.com.Dispatch; /** * Snippet to show Visio print dialog *

- * Sample submitted by fatbuttlarry in SourceForge 1803140 - * as part of bug report + * Sample submitted by fatbuttlarry in SourceForge 1803140 as part of bug report *

* Tested with Java 6.0SE and MS Office 2003 ** Note: 1010 = VB's * visCmdFilePrint constant @@ -26,8 +25,7 @@ public class VisioPrintTest { // create a blank document Dispatch.call(oDocuments, "Add", ""); try { - Dispatch.call(oActiveX, "DoCmd", new Integer(1010)) - .getInt(); + Dispatch.call(oActiveX, "DoCmd", new Integer(1010)).getInt(); System.out.println("User hit the ok button."); } catch (ComFailException e) { System.out.println("User hit the cancel button: " + e); @@ -37,7 +35,12 @@ public class VisioPrintTest { return; } - /** quick main() to test this */ + /** + * quick main() to test this + * + * @param args + * standard command line arguments + */ public static void main(String[] args) { VisioPrintTest testObject = new VisioPrintTest(); testObject.testPrintDialog(); diff --git a/samples/com/jacob/samples/office/WordDocumentProperties.java b/samples/com/jacob/samples/office/WordDocumentProperties.java index 978415e..8bb090d 100644 --- a/samples/com/jacob/samples/office/WordDocumentProperties.java +++ b/samples/com/jacob/samples/office/WordDocumentProperties.java @@ -14,150 +14,152 @@ import com.jacob.com.Variant; * are sections that could be enhanced */ public class WordDocumentProperties { - //Declare word object - private ActiveXComponent objWord; + // Declare word object + private ActiveXComponent objWord; - //Declare Word Properties - private Dispatch custDocprops; + // Declare Word Properties + 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 - //private Dispatch documents; + // the doucments object is important in any real app but this demo doesn't + // use it + // private Dispatch documents; - private Dispatch document; + private Dispatch document; - private Dispatch wordObject; + private Dispatch wordObject; - /** - * Empty Constructor - * - */ - public WordDocumentProperties() { - } + /** + * Empty Constructor + * + */ + public WordDocumentProperties() { + } - /** - * Opens a document - * - * @param filename - */ - public void open(String filename) { - //Instantiate objWord - objWord = new ActiveXComponent("Word.Application"); + /** + * Opens a document + * + * @param filename + */ + public void open(String filename) { + // Instantiate objWord + objWord = new ActiveXComponent("Word.Application"); - //Assign a local word object - wordObject = objWord.getObject(); + // Assign a local word object + wordObject = objWord.getObject(); - //Create a Dispatch Parameter to hide the document that is opened - Dispatch.put((Dispatch) wordObject, "Visible", new Variant(false)); + // Create a Dispatch Parameter to hide the document that is opened + Dispatch.put(wordObject, "Visible", new Variant(false)); - //Instantiate the Documents Property - Dispatch documents = objWord.getProperty("Documents").toDispatch(); + // Instantiate the Documents Property + Dispatch documents = objWord.getProperty("Documents").toDispatch(); - //Open a word document, Current Active Document - document = Dispatch.call(documents, "Open", filename).toDispatch(); - } + // Open a word document, Current Active Document + document = Dispatch.call(documents, "Open", filename).toDispatch(); + } - /** - * Creates an instance of the VBA CustomDocumentProperties property - * - */ - public void selectCustomDocumentProperitiesMode() { - //Create CustomDocumentProperties and BuiltInDocumentProperties - // properties - custDocprops = Dispatch.get(document, "CustomDocumentProperties") - .toDispatch(); - } + /** + * Creates an instance of the VBA CustomDocumentProperties property + * + */ + public void selectCustomDocumentProperitiesMode() { + // Create CustomDocumentProperties and BuiltInDocumentProperties + // properties + custDocprops = Dispatch.get(document, "CustomDocumentProperties") + .toDispatch(); + } - /** - * Creates an instance of the VBA BuiltInDocumentProperties property - * - */ - public void selectBuiltinPropertiesMode() { - //Create CustomDocumentProperties and BuiltInDocumentProperties - // properties - builtInDocProps = Dispatch.get(document, "BuiltInDocumentProperties") - .toDispatch(); - } + /** + * Creates an instance of the VBA BuiltInDocumentProperties property + * + */ + public void selectBuiltinPropertiesMode() { + // Create CustomDocumentProperties and BuiltInDocumentProperties + // properties + builtInDocProps = Dispatch.get(document, "BuiltInDocumentProperties") + .toDispatch(); + } - /** - * Closes a document - * - */ - public void close() { - //Close object - Dispatch.call(document, "Close"); - } + /** + * Closes a document + * + */ + public void close() { + // Close object + Dispatch.call(document, "Close"); + } - /** - * Custom Property Name is passed in - * - * @param cusPropName - * @return String - Custom property value - */ - public String getCustomProperty(String cusPropName) { - try { - cusPropName = Dispatch.call((Dispatch) custDocprops, "Item", - cusPropName).toString(); - } catch (ComException e) { - // Do nothing - cusPropName = null; - } + /** + * Custom Property Name is passed in + * + * @param cusPropName + * @return String - Custom property value + */ + public String getCustomProperty(String cusPropName) { + try { + cusPropName = Dispatch.call(custDocprops, "Item", cusPropName) + .toString(); + } catch (ComException e) { + // Do nothing + cusPropName = null; + } - return cusPropName; - } + return cusPropName; + } - /** - * Built In Property Name is passed in - * - * @param builtInPropName - * @return String - Built in property value - */ - public String getBuiltInProperty(String builtInPropName) { - try { - builtInPropName = Dispatch.call((Dispatch) builtInDocProps, "Item", - builtInPropName).toString(); - } catch (ComException e) { - // Do nothing - builtInPropName = null; - } + /** + * Built In Property Name is passed in + * + * @param builtInPropName + * @return String - Built in property value + */ + public String getBuiltInProperty(String builtInPropName) { + try { + builtInPropName = Dispatch.call(builtInDocProps, "Item", + builtInPropName).toString(); + } catch (ComException e) { + // Do nothing + builtInPropName = null; + } - return builtInPropName; - } + return builtInPropName; + } - /** - * simple main program that gets some properties and prints them out - * @param args - */ - public static void main(String[] args) { - try { - //Instantiate the class - WordDocumentProperties jacTest = new WordDocumentProperties(); + /** + * simple main program that gets some properties and prints them out + * + * @param args + */ + public static void main(String[] args) { + try { + // Instantiate the class + WordDocumentProperties jacTest = new WordDocumentProperties(); - //Open the word doc - jacTest.open("\\\\Saturn\\documentstorage\\s.doc"); + // Open the word doc + jacTest.open("\\\\Saturn\\documentstorage\\s.doc"); - //Set Custom Properties - jacTest.selectCustomDocumentProperitiesMode(); + // Set Custom Properties + jacTest.selectCustomDocumentProperitiesMode(); - //Set Built In Properties - jacTest.selectBuiltinPropertiesMode(); + // Set Built In Properties + jacTest.selectBuiltinPropertiesMode(); - //Get custom Property Value - String custValue = jacTest.getCustomProperty("Information Source"); + // Get custom Property Value + String custValue = jacTest.getCustomProperty("Information Source"); - //Get built in prroperty Property Value - String builtInValue = jacTest.getBuiltInProperty("Author"); + // Get built in prroperty Property Value + String builtInValue = jacTest.getBuiltInProperty("Author"); - //Close Word Doc - jacTest.close(); + // Close Word Doc + jacTest.close(); - //Output data - System.out.println("Document Val One: " + custValue); - System.out.println("Document Author: " + builtInValue); + // Output data + System.out.println("Document Val One: " + custValue); + System.out.println("Document Author: " + builtInValue); - } catch (Exception e) { - System.out.println(e); - } - } + } catch (Exception e) { + System.out.println(e); + } + } } \ No newline at end of file diff --git a/samples/com/jacob/samples/outlook/Outlook.java b/samples/com/jacob/samples/outlook/Outlook.java index 4d82bd4..018091d 100644 --- a/samples/com/jacob/samples/outlook/Outlook.java +++ b/samples/com/jacob/samples/outlook/Outlook.java @@ -5,65 +5,76 @@ package com.jacob.samples.outlook; * Christopher Brind */ -import com.jacob.com.*; -import com.jacob.activeX.*; - +import com.jacob.activeX.ActiveXComponent; +import com.jacob.com.Dispatch; +import com.jacob.com.Variant; +/** + * sample class to show simple outlook manipulation + */ public class Outlook { - private static String pad(int i) { - StringBuffer sb = new StringBuffer(); + private static String pad(int i) { + StringBuffer sb = new StringBuffer(); - while(sb.length() < i) { - sb.append(' '); - } + while (sb.length() < i) { + 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 oFolders = Dispatch.get(o, "Folders").toDispatch(); - // System.out.println("oFolders=" + oFolders); - if (oFolders == null) return; + Dispatch oFolder = Dispatch.get(oFolders, "GetFirst").toDispatch(); + do { + Object oFolderName = Dispatch.get(oFolder, "Name"); + if (null == oFolderName) { + break; + } - Dispatch oFolder = Dispatch.get(oFolders, "GetFirst").toDispatch(); - do { - Object oFolderName = Dispatch.get(oFolder, "Name"); - if (null == oFolderName) { - break; - } + System.out.println(pad(iIndent) + oFolderName); + recurseFolders(iIndent + 3, oFolder); - System.out.println(pad(iIndent) + oFolderName); - recurseFolders(iIndent + 3, oFolder); + oFolder = Dispatch.get(oFolders, "GetNext").toDispatch(); + } 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 { - System.out.println("Outlook: IN"); + Dispatch oOutlook = axOutlook.getObject(); + System.out.println("version=" + Dispatch.get(oOutlook, "Version")); - ActiveXComponent axOutlook = new ActiveXComponent("Outlook.Application"); - try { - System.out.println("version="+axOutlook.getProperty("Version")); + Dispatch oNameSpace = axOutlook.getProperty("Session").toDispatch(); + System.out.println("oNameSpace=" + oNameSpace); - Dispatch oOutlook = axOutlook.getObject(); - System.out.println("version="+Dispatch.get(oOutlook, "Version")); + recurseFolders(0, oNameSpace); - Dispatch oNameSpace = axOutlook.getProperty("Session").toDispatch(); - System.out.println("oNameSpace=" + oNameSpace); - - recurseFolders(0, oNameSpace); - - } finally { - axOutlook.invoke("Quit", new Variant[] {}); - } - } + } finally { + axOutlook.invoke("Quit", new Variant[] {}); + } + } } - diff --git a/samples/com/jacob/samples/system/DiskUtils.java b/samples/com/jacob/samples/system/DiskUtils.java index 1af1c9a..93a0621 100644 --- a/samples/com/jacob/samples/system/DiskUtils.java +++ b/samples/com/jacob/samples/system/DiskUtils.java @@ -10,41 +10,49 @@ import com.jacob.com.Variant; /** * Example VB script that grabs hard drive properties. *

- * 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 *

- * 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 { /** 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 */ private ActiveXComponent fileSystemApp = null; - + /** the dispatch that points at the drive this DiskUtil operates against */ private Dispatch myDrive = null; - + /** * Standard constructor + * + * @param drive + * the drive to run the test against. */ - public DiskUtils(String drive){ + public DiskUtils(String drive) { setUp(drive); } - + /** * open the connection to the scripting object + * + * @param drive + * the drive to run the test against */ - public void setUp(String drive){ - if (fileSystemApp == null){ - ComThread.InitSTA(); - fileSystemApp = new ActiveXComponent( - "Scripting.FileSystemObject"); + public void setUp(String drive) { + if (fileSystemApp == null) { + ComThread.InitSTA(); + fileSystemApp = new ActiveXComponent("Scripting.FileSystemObject"); myDrive = Dispatch.call(fileSystemApp, "GetDrive", drive) - .toDispatch(); + .toDispatch(); } } @@ -54,58 +62,61 @@ public class DiskUtils { public void tearDown() { ComThread.Release(); } - + /** * convenience method + * * @return driver serial number */ public int getSerialNumber() { return Dispatch.get(myDrive, "SerialNumber").getInt(); } - + /** - * Convenience method. - * We go through these formatting hoops so we can make the size string pretty. - * We wouldn't have to do that if we didn't mind long strings with Exxx at the end - * or the fact that the value returned can vary in size based on the size of the disk. + * Convenience method. We go through these formatting hoops so we can make + * the size string pretty. We wouldn't have to do that if we didn't mind + * long strings with Exxx at the end or the fact that the value returned can + * vary in size based on the size of the disk. + * * @return driver total size of the disk */ public String getTotalSize() { Variant returnValue = Dispatch.get(myDrive, "TotalSize"); - if (returnValue.getvt() == Variant.VariantDouble){ + if (returnValue.getvt() == Variant.VariantDouble) { return sizeFormatter.format(returnValue.getDouble()); - } else if (returnValue.getvt() == Variant.VariantInt){ + } else if (returnValue.getvt() == Variant.VariantInt) { return sizeFormatter.format(returnValue.getInt()); } else { - return "Don't know type: "+returnValue.getvt(); + return "Don't know type: " + returnValue.getvt(); } } - + /** - * Convenience method. - * We wouldn't have to do that if we didn't mind long strings with Exxx at the end - * or the fact that the value returned can vary in size based on the size of the disk. + * Convenience method. We wouldn't have to do that if we didn't mind long + * strings with Exxx at the end or the fact that the value returned can vary + * in size based on the size of the disk. + * * @return driver free size of the disk */ public String getFreeSpace() { Variant returnValue = Dispatch.get(myDrive, "FreeSpace"); - if (returnValue.getvt() == Variant.VariantDouble){ + if (returnValue.getvt() == Variant.VariantDouble) { return sizeFormatter.format(returnValue.getDouble()); - } else if (returnValue.getvt() == Variant.VariantInt){ + } else if (returnValue.getvt() == Variant.VariantInt) { return sizeFormatter.format(returnValue.getInt()); } else { - return "Don't know type: "+returnValue.getvt(); + return "Don't know type: " + returnValue.getvt(); } } - + /** * * @return file system on the drive */ public String getFileSystemType() { - //figure ot the actual variant type - //Variant returnValue = Dispatch.get(myDrive, "FileSystem"); - //System.out.println(returnValue.getvt()); + // figure ot the actual variant type + // Variant returnValue = Dispatch.get(myDrive, "FileSystem"); + // System.out.println(returnValue.getvt()); return Dispatch.get(myDrive, "FileSystem").getString(); } @@ -116,17 +127,26 @@ public class DiskUtils { public String getVolumeName() { 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) { - //DiskUtils utilConnection = new DiskUtils("F"); + // DiskUtils utilConnection = new DiskUtils("F"); DiskUtils utilConnection = new DiskUtils("C"); - System.out.println("Disk serial number is: "+ utilConnection.getSerialNumber()); - System.out.println("FileSystem is: "+ utilConnection.getFileSystemType()); - 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()); + System.out.println("Disk serial number is: " + + utilConnection.getSerialNumber()); + System.out.println("FileSystem is: " + + utilConnection.getFileSystemType()); + 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(); } } diff --git a/samples/com/jacob/samples/system/SystemMonitor.java b/samples/com/jacob/samples/system/SystemMonitor.java index 9258145..a3a05a1 100644 --- a/samples/com/jacob/samples/system/SystemMonitor.java +++ b/samples/com/jacob/samples/system/SystemMonitor.java @@ -13,23 +13,27 @@ import com.jacob.com.Variant; * fold, spindled and mutilated by clay_shooter * * @author chris_knowles - * + * */ public class SystemMonitor { + /** + * example run loop method called by main() + */ public void runMonitor() { ActiveXComponent wmi = null; wmi = new ActiveXComponent("WbemScripting.SWbemLocator"); // no connection parameters means to connect to the local machine 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()); // the WMI supports a query language. String query = "select CategoryString, Message, TimeGenerated, User, Type " - + "from Win32_NtLogEvent " - + "where Logfile = 'Application' and TimeGenerated > '20070915000000.000000-***'"; + + "from Win32_NtLogEvent " + + "where Logfile = 'Application' and TimeGenerated > '20070915000000.000000-***'"; Variant vCollection = wmiconnect .invoke("ExecQuery", new Variant(query)); @@ -40,7 +44,7 @@ public class SystemMonitor { while (enumVariant.hasMoreElements()) { resultString = ""; - item = enumVariant.Next().toDispatch(); + item = enumVariant.nextElement().toDispatch(); String categoryString = Dispatch.call(item, "CategoryString") .toString(); String messageString = Dispatch.call(item, "Message").toString(); @@ -48,17 +52,21 @@ public class SystemMonitor { .toString(); String eventUser = Dispatch.call(item, "User").toString(); String eventType = Dispatch.call(item, "Type").toString(); - resultString += "TimeGenerated: "+ timeGenerated - + " Category: " + categoryString - + " User: " + eventUser - + " EventType: "+ eventType - + " Message:" + messageString; + resultString += "TimeGenerated: " + timeGenerated + " Category: " + + categoryString + " User: " + eventUser + " EventType: " + + eventType + " Message:" + messageString; System.out.println(resultString); } } + /** + * sample's main program + * + * @param args + * command line arguments + */ public static void main(String[] args) { SystemMonitor utilConnection = new SystemMonitor(); utilConnection.runMonitor(); diff --git a/samples/com/jacob/samples/visio/VisioApp.java b/samples/com/jacob/samples/visio/VisioApp.java index 4f28247..d1c8337 100644 --- a/samples/com/jacob/samples/visio/VisioApp.java +++ b/samples/com/jacob/samples/visio/VisioApp.java @@ -1,85 +1,121 @@ package com.jacob.samples.visio; -import com.jacob.com.*; -import com.jacob.activeX.*; 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 - * + * * This class represents the visio app itself */ 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"); - setVisible(false); - } + /** + * creates a DispatchEvents object to register o as a listener + * + * @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 - * @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"); - } - } + /** + * opens the passed in file in Visio + * + * @param f + * @throws VisioException + */ + public void open(File f) throws VisioException { + 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 { - 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); - } - } + /** + * terminates Visio + */ + public void quit() { + System.out.println("Received quit()"); + // there can't be any open documents for this to work + // you'll get a visio error if you don't close them + ActiveXComponent document = new ActiveXComponent(getProperty( + "ActiveDocument").toDispatch()); + document.invoke("Close"); + invoke("Quit"); + } - 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); - } - } + /** + * runs the Visio export command + * + * @param f + * @throws VisioException + */ + 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 - */ - public void quit() { - System.out.println("Received quit()"); - // there can't be any open documents for this to work - // you'll get a visio error if you don't close them - ActiveXComponent document = new ActiveXComponent(getProperty("ActiveDocument").toDispatch()); - document.invoke("Close"); - invoke("Quit"); - } - - 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); - } - } + /** + * makes Visio visible so the user can watch + * + * @param b + * @throws VisioException + */ + public void setVisible(boolean b) throws VisioException { + try { + setProperty("Visible", new Variant(b)); + } catch (Exception e) { + throw new VisioException(e); + } + } } diff --git a/samples/com/jacob/samples/visio/VisioAppFacade.java b/samples/com/jacob/samples/visio/VisioAppFacade.java index fbd5bac..9395f84 100644 --- a/samples/com/jacob/samples/visio/VisioAppFacade.java +++ b/samples/com/jacob/samples/visio/VisioAppFacade.java @@ -1,120 +1,180 @@ 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 - * + * * 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 - * called. Direct consumption of VisioApp would mean you could quit but would - * still have a handle to the no longer connected application proxy + * you can't try and send messages to a dead Visio instance after quit() has + * been called. Direct consumption of VisioApp would mean you could quit but + * would still have a handle to the no longer connected application proxy * */ public class VisioAppFacade { + private VisioApp app; + private static VisioAppFacade instance; - private VisioApp app; - private static VisioAppFacade instance; + /** extension for image files */ + 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"; - public static final int BUFFER_SIZE = 2048; - - private VisioAppFacade() throws VisioException { - this.app = new VisioApp(); + /** + * Wrapper around Visio + * + * @throws VisioException + */ + private VisioAppFacade() throws VisioException { + this.app = new VisioApp(); app.addEventListener(new VisioEventAdapter(app)); - } + } - public static VisioAppFacade getInstance() throws VisioException { - if (instance == null) { - instance = new VisioAppFacade(); - } - return instance; - } + /** + * @return the singleton instance of Visio + * @throws VisioException + */ + public static VisioAppFacade getInstance() throws VisioException { + if (instance == null) { + instance = new VisioAppFacade(); + } + return instance; + } - public byte[] createPreview(byte[] visioData) throws VisioException { - byte[] preview; - File tmpFile; - try { - tmpFile = getTempVisioFile(); - OutputStream out = new FileOutputStream(tmpFile); - out.write(visioData); - out.close(); - } catch (IOException ioe) { - throw new VisioException(ioe); - } - preview = createPreview(tmpFile); - tmpFile.delete(); - return preview; - } + /** + * creates a preview in a temp file and returns the raw data. + * + * @param visioData + * @return raw preview data + * @throws VisioException + */ + public byte[] createPreview(byte[] visioData) throws VisioException { + byte[] preview; + File tmpFile; + try { + tmpFile = getTempVisioFile(); + OutputStream out = new FileOutputStream(tmpFile); + 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 { - File imageFile; - imageFile = getTempImageFile(); - app.open(visioFile); - app.export(imageFile); - ByteArrayOutputStream bout = new ByteArrayOutputStream(); - FileInputStream fin = new FileInputStream(imageFile); - copy(fin, bout); - fin.close(); - imageFile.delete(); - bout.close(); - return bout.toByteArray(); - } catch (IOException ioe) { - throw new VisioException(ioe); - } - } + /** + * reads a preview from a saved file + * + * @param visioFile + * @return raw preview data + * @throws VisioException + */ + public byte[] createPreview(File visioFile) throws VisioException { + try { + File imageFile; + imageFile = getTempImageFile(); + app.open(visioFile); + app.export(imageFile); + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + 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 { - byte[] buff = new byte[BUFFER_SIZE]; - int read; - do { - read = in.read(buff); - if (read > 0) { - out.write(buff,0,read); - } - } while (read > 0); - } + private void copy(InputStream in, OutputStream out) throws IOException { + byte[] buff = new byte[BUFFER_SIZE]; + int read; + do { + read = in.read(buff); + if (read > 0) { + out.write(buff, 0, read); + } + } while (read > 0); + } - public byte[] createPreview(InputStream in) throws VisioException { - byte[] preview; - //byte[] buff = new byte[2048]; - //int read = 0; - OutputStream out; - File tmpFile; + /** + * creates a preview from an input stream + * + * @param in + * @return byte contents of the preview stream + * @throws VisioException + */ + public byte[] createPreview(InputStream in) throws VisioException { + byte[] preview; + // byte[] buff = new byte[2048]; + // int read = 0; + OutputStream out; + File tmpFile; - try { - tmpFile = getTempVisioFile(); - out = new FileOutputStream(tmpFile); - copy(in, out); - out.close(); - } catch (IOException ioe) { - throw new VisioException(ioe); - } + try { + tmpFile = getTempVisioFile(); + out = new FileOutputStream(tmpFile); + copy(in, out); + out.close(); + } catch (IOException ioe) { + throw new VisioException(ioe); + } - preview = createPreview(tmpFile); - tmpFile.delete(); - return preview; - } + preview = createPreview(tmpFile); + tmpFile.delete(); + return preview; + } - public void editDiagram(File f) throws VisioException { - app.open(f); - app.setVisible(true); - } + /** + * opens the file in Visio and makes the editor visible + * + * @param f + * the reference to the Visio file to be opened + * @throws VisioException + */ + public void editDiagram(File f) throws VisioException { + 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() { - app.quit(); - instance = null; - } + /** exit visio */ + public void quit() { + app.quit(); + instance = null; + } } diff --git a/samples/com/jacob/samples/visio/VisioDemo.java b/samples/com/jacob/samples/visio/VisioDemo.java index 745c647..7cb6c8d 100644 --- a/samples/com/jacob/samples/visio/VisioDemo.java +++ b/samples/com/jacob/samples/visio/VisioDemo.java @@ -1,177 +1,197 @@ 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 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 - *

- * This file contains the main() that runs the demo - *

- * Look in the docs area at the Jacob usage document for command line options. + *

+ * This file contains the main() that runs the demo + *

+ * Look in the docs area at the Jacob usage document for command line + * options. */ public class VisioDemo extends JFrame implements ActionListener, WindowListener { - /** + /** * Totally dummy value to make Eclipse quit complaining */ private static final long serialVersionUID = 1L; - + JButton chooseButton; - JButton openButton; - JPanel buttons; + JButton openButton; + JPanel buttons; - ImageIcon theImage; - JLabel theLabel; // the icon on the page is actually this button's icon + ImageIcon theImage; + JLabel theLabel; // the icon on the page is actually this button's icon - File selectedFile; - /** everyone should get this through getVisio() */ - private VisioAppFacade visioProxy = null; + File selectedFile; + /** everyone should get this through getVisio() */ + private VisioAppFacade visioProxy = null; - // put this up here so it remembers where we were on the last choose - JFileChooser chooser = null; - + // put this up here so it remembers where we were on the last choose + JFileChooser chooser = null; - public class VisioFileFilter extends FileFilter { - public boolean accept(File f) { - if (f.isDirectory()){ - return true; - } else { - return (f.getName().toUpperCase().endsWith(".VSD")); - } - } + public class VisioFileFilter extends FileFilter { + public boolean accept(File f) { + if (f.isDirectory()) { + return true; + } else { + return (f.getName().toUpperCase().endsWith(".VSD")); + } + } - public String getDescription() { - return "Visio Drawings"; - } - } + public String getDescription() { + return "Visio Drawings"; + } + } - public VisioDemo() { - super("Visio in Swing POC"); - this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - buttons = new JPanel(); - getContentPane().setLayout(new BorderLayout()); - chooseButton = new JButton("Choose file to display"); - openButton = new JButton("Open file chosen file in Visio"); - chooseButton.addActionListener(this); - openButton.addActionListener(this); - buttons.add(chooseButton); - buttons.add(openButton); - getContentPane().add(buttons, BorderLayout.SOUTH); - theLabel = new JLabel(""); - getContentPane().add(theLabel, BorderLayout.CENTER); - addWindowListener(this); - setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); - setSize(640,480); - this.setVisible(true); - } + public VisioDemo() { + super("Visio in Swing POC"); + this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + buttons = new JPanel(); + getContentPane().setLayout(new BorderLayout()); + chooseButton = new JButton("Choose file to display"); + openButton = new JButton("Open file chosen file in Visio"); + chooseButton.addActionListener(this); + openButton.addActionListener(this); + buttons.add(chooseButton); + buttons.add(openButton); + getContentPane().add(buttons, BorderLayout.SOUTH); + theLabel = new JLabel(""); + getContentPane().add(theLabel, BorderLayout.CENTER); + addWindowListener(this); + setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + setSize(640, 480); + this.setVisible(true); + } - public static void main(String args[]) throws Exception { - SwingUtilities.invokeLater(new Runnable(){ - public void run(){ - ComThread.InitSTA(); - VisioDemo poc = new VisioDemo(); - ComThread.Release(); - if (poc == null){ - System.out.println("poc== null? That should never happen!"); - } - } - }); - } + public static void main(String args[]) throws Exception { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + ComThread.InitSTA(); + VisioDemo poc = new VisioDemo(); + ComThread.Release(); + if (poc == null) { + System.out.println("poc== null? That should never happen!"); + } + } + }); + } - public void actionPerformed(ActionEvent e) { - if (e.getSource() == chooseButton) { - pickFile(); - } else if (e.getSource() == openButton) { - try { - openFile(); - } catch (Exception ex) { - ex.printStackTrace(); - throw new RuntimeException(ex); - } - } else { - System.out.println("Awesome!"); - } - } + public void actionPerformed(ActionEvent e) { + if (e.getSource() == chooseButton) { + pickFile(); + } else if (e.getSource() == openButton) { + try { + openFile(); + } catch (Exception ex) { + ex.printStackTrace(); + throw new RuntimeException(ex); + } + } else { + System.out.println("Awesome!"); + } + } - private void pickFile() { - try { - chooser = new JFileChooser(); - // comment this out if you want it to always go to myDocuments - chooser.setCurrentDirectory(new File(System.getProperty("user.dir"))); - chooser.setFileFilter(new VisioFileFilter()); - int returnVal = chooser.showOpenDialog(this); - if(returnVal == JFileChooser.APPROVE_OPTION) { - selectedFile = chooser.getSelectedFile(); - showSelectedFilePreview(); - } - } catch (Exception e) { - e.printStackTrace(); - } - } + private void pickFile() { + try { + chooser = new JFileChooser(); + // comment this out if you want it to always go to myDocuments + chooser + .setCurrentDirectory(new File(System + .getProperty("user.dir"))); + chooser.setFileFilter(new VisioFileFilter()); + int returnVal = chooser.showOpenDialog(this); + if (returnVal == JFileChooser.APPROVE_OPTION) { + selectedFile = chooser.getSelectedFile(); + showSelectedFilePreview(); + } + } catch (Exception e) { + e.printStackTrace(); + } + } - /** - * use this private method instead of initializing on boot up so that instance - * and all listeners are created in this thread (event thread) rather than root thread - * @return - */ - private VisioAppFacade getVisio(){ - if (visioProxy == null){ - try { - visioProxy = VisioAppFacade.getInstance(); - } catch (VisioException ve){ - System.out.println("ailed to openFile()"); - ve.printStackTrace(); - } - } - return visioProxy; - } - private void showSelectedFilePreview() throws VisioException { - if (selectedFile != null) { - byte[] image = getVisio().createPreview(selectedFile); - theImage = new ImageIcon(image); - theLabel.setIcon(theImage); - } - } + /** + * use this private method instead of initializing on boot up so that + * instance and all listeners are created in this thread (event thread) + * rather than root thread + * + * @return + */ + private VisioAppFacade getVisio() { + if (visioProxy == null) { + try { + visioProxy = VisioAppFacade.getInstance(); + } catch (VisioException ve) { + System.out.println("ailed to openFile()"); + ve.printStackTrace(); + } + } + return visioProxy; + } - private void openFile() throws VisioException { - try { - getVisio().editDiagram(selectedFile); - showSelectedFilePreview(); - } catch (VisioException ve){ - System.out.println("ailed to openFile()"); - ve.printStackTrace(); - } + private void showSelectedFilePreview() throws VisioException { + if (selectedFile != null) { + byte[] image = getVisio().createPreview(selectedFile); + theImage = new ImageIcon(image); + theLabel.setIcon(theImage); + } + } - } + 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) { - System.out.println("WINDOW CLOSED"); - if (visioProxy != null){ - visioProxy.quit(); - } - } - public void windowClosing(WindowEvent e){ - } + public void windowActivated(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){ - System.out.println("Fooboo"); - } - public void windowOpened(WindowEvent e){ - } + public void windowDeactivated(WindowEvent e) { + } + + public void windowDeiconified(WindowEvent e) { + } + + public void windowIconified(WindowEvent e) { + System.out.println("Fooboo"); + } + + public void windowOpened(WindowEvent e) { + } } diff --git a/samples/com/jacob/samples/visio/VisioEventAdapter.java b/samples/com/jacob/samples/visio/VisioEventAdapter.java index 77b91a6..2923310 100644 --- a/samples/com/jacob/samples/visio/VisioEventAdapter.java +++ b/samples/com/jacob/samples/visio/VisioEventAdapter.java @@ -1,59 +1,68 @@ 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 - * - * 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 { VisioApp app = null; - - public VisioEventAdapter(VisioApp pApp){ + + public VisioEventAdapter(VisioApp pApp) { app = pApp; System.out.println("Event listener constructed"); } - - public void BeforeQuit(Variant[] args){ } - public void DocumentChanged(Variant[] args){ - System.out.println("documentChanged()"); - } + public void BeforeQuit(Variant[] args) { + } - 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){ - System.out.println("DocumentOpened()"); - } + public void DocumentCreated(Variant[] args) { + } - 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){ - 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) { - // these may throw VisioException - System.out.println("Saving document, hiding and telling visio not to quit"); - try { - app.save(); - app.setVisible(false); - } catch (VisioException ve){ - System.out.println("ailed to openFile()"); - ve.printStackTrace(); - } - return new Variant(true); - } + public void DocumentSavedAs(Variant[] args) { + } + + 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) { + // these may throw VisioException + System.out + .println("Saving document, hiding and telling visio not to quit"); + try { + app.save(); + app.setVisible(false); + } catch (VisioException ve) { + System.out.println("ailed to openFile()"); + ve.printStackTrace(); + } + return new Variant(true); + } } - diff --git a/samples/com/jacob/samples/visio/VisioEventListener.java b/samples/com/jacob/samples/visio/VisioEventListener.java index 3303045..97ea2f9 100644 --- a/samples/com/jacob/samples/visio/VisioEventListener.java +++ b/samples/com/jacob/samples/visio/VisioEventListener.java @@ -1,33 +1,33 @@ 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 - * - * There are many more Visio events available. See the Microsoft - * Office SDK documentation. To receive an event, add a method to this interface - * whose name matches the event name and has only one parameter, Variant[]. - * The JACOB library will use reflection to call that method when an event is received. + * + * There are many more Visio events available. See the Microsoft Office SDK + * documentation. To receive an event, add a method to this interface whose name + * matches the event name and has only one parameter, Variant[]. The JACOB + * library will use reflection to call that method when an event is received. */ 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); } - diff --git a/samples/com/jacob/samples/visio/VisioException.java b/samples/com/jacob/samples/visio/VisioException.java index 1a055cb..06edd08 100644 --- a/samples/com/jacob/samples/visio/VisioException.java +++ b/samples/com/jacob/samples/visio/VisioException.java @@ -1,22 +1,25 @@ 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 - * - * 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 { - /** + /** * Totally dummy value to make Eclipse quit complaining */ private static final long serialVersionUID = 1L; public VisioException(String msg) { - super(msg); - } + super(msg); + } - public VisioException(Throwable cause) { - super(cause); - } + public VisioException(Throwable cause) { + super(cause); + } } diff --git a/src/com/jacob/activeX/ActiveXComponent.java b/src/com/jacob/activeX/ActiveXComponent.java index 39c2f82..a5dc44d 100644 --- a/src/com/jacob/activeX/ActiveXComponent.java +++ b/src/com/jacob/activeX/ActiveXComponent.java @@ -19,532 +19,561 @@ */ package com.jacob.activeX; -import com.jacob.com.*; +import com.jacob.com.Dispatch; +import com.jacob.com.JacobObject; +import com.jacob.com.Variant; /** - * This class provides a higher level, more object like, wrapper for - * top of the Dispatch object. The Dispatch class's method essentially - * directly map to Microsoft C API including the first parameter that is - * almost always the target of the message. - * ActiveXComponent assumes the target of every message is the MS - * COM object behind the ActiveXComponent. This removes the need - * to pass the Dispatch object into every method. + * This class provides a higher level, more object like, wrapper for top of the + * Dispatch object. The Dispatch class's method essentially directly map to + * Microsoft C API including the first parameter that is almost always the + * target of the message. ActiveXComponent assumes the target of every message + * is the MS COM object behind the ActiveXComponent. This removes the need to + * pass the Dispatch object into every method. *

- * It is really up to the developer as to whether they want to - * use the Dispatch interface or the ActiveXComponent interface. + * It is really up to the developer as to whether they want to use the Dispatch + * interface or the ActiveXComponent interface. *

- * This class simulates com.ms.activeX.ActiveXComponent only in - * the senese that it is used for creating Dispatch objects + * This class simulates com.ms.activeX.ActiveXComponent only in the sense that + * it is used for creating Dispatch objects */ public class ActiveXComponent extends Dispatch { /** - * Normally used to create a new connection to a microsoft application. - * The passed in parameter is the name of the program as registred - * in the registry. It can also be the object name. - *

- * This constructor causes a new Windows object of the requested - * type to be created. The windows CoCreate() function gets called - * to create the underlying windows object. - * - *

new ActiveXComponent("ScriptControl");
- * @param programId - */ - public ActiveXComponent(String programId) { - super(programId); - } + * Normally used to create a new connection to a microsoft application. The + * passed in parameter is the name of the program as registered in the + * registry. It can also be the object name. + *

+ * This constructor causes a new Windows object of the requested type to be + * created. The windows CoCreate() function gets called to create the + * underlying windows object. + * + *

+	 * new ActiveXComponent("ScriptControl");
+	 * 
+ * + * @param programId + */ + public ActiveXComponent(String programId) { + super(programId); + } - /** - * Creates an active X component that is built on top of the - * COM pointers held in the passed in dispatch. - * This widends the Dispatch object to pick up the ActiveXComponent API - * - * @param dispatchToBeWrapped - */ - public ActiveXComponent(Dispatch dispatchToBeWrapped) { - super(dispatchToBeWrapped); - } + /** + * Creates an active X component that is built on top of the COM pointers + * held in the passed in dispatch. This widens the Dispatch object to pick + * up the ActiveXComponent API + * + * @param dispatchToBeWrapped + */ + public ActiveXComponent(Dispatch dispatchToBeWrapped) { + super(dispatchToBeWrapped); + } - /** - * only used by the factories - * - */ - private ActiveXComponent() { - super(); - } + /** + * only used by the factories + * + */ + private ActiveXComponent() { + super(); + } - /** - * Probably was a cover for something else in the past. - * Should be deprecated. - * @return Now it actually returns this exact same object. - */ - public Dispatch getObject() { - return this; - } + /** + * Probably was a cover for something else in the past. Should be + * deprecated. + * + * @return Now it actually returns this exact same object. + */ + public Dispatch getObject() { + return this; + } - /** - * Most code should use the standard ActiveXComponent(String) contructor - * and not this factory method. This method exists for applications - * that need special behavior. - * Experimental in release 1.9.2. - *

- * Factory that returns a Dispatch object wrapped around the result - * of a CoCreate() call. This differs from the standard constructor - * in that it throws no exceptions and returns null on failure. - *

- * This will fail for any prog id with a ":" in it. - * - * @param pRequestedProgramId - * @return Dispatch pointer to the COM object or null if couldn't create - */ - public static ActiveXComponent createNewInstance(String pRequestedProgramId){ - ActiveXComponent mCreatedDispatch = null; - try { - mCreatedDispatch = new ActiveXComponent(); - mCreatedDispatch.coCreateInstance(pRequestedProgramId); - } catch (Exception e){ - mCreatedDispatch =null; - if (JacobObject.isDebugEnabled()){ - JacobObject.debug("Unable to co-create instance of "+pRequestedProgramId); - } - } - return mCreatedDispatch; - } - - /** - * Most code should use the standard ActiveXComponent(String) contructor - * and not this factory method. This method exists for applications - * that need special behavior. - * Experimental in release 1.9.2. - *

- * Factory that returns a Dispatch wrapped around the result - * of a getActiveObject() call. This differs from the standard constructor - * in that it throws no exceptions and returns null on failure. - *

- * This will fail for any prog id with a ":" in it - * - * @param pRequestedProgramId - * @return Dispatch pointer to a COM object or null if wasn't already running - */ - public static ActiveXComponent connectToActiveInstance(String pRequestedProgramId){ - ActiveXComponent mCreatedDispatch = null; - try { - mCreatedDispatch = new ActiveXComponent(); - mCreatedDispatch.getActiveInstance(pRequestedProgramId); - } catch (Exception e){ - mCreatedDispatch =null; - if (JacobObject.isDebugEnabled()){ - JacobObject.debug("Unable to attach to running instance of "+pRequestedProgramId); - } - } - return mCreatedDispatch; - } - - /** - * @see com.jacob.com.Dispatch#finalize() - */ - protected void finalize() { - super.finalize(); - } + /** + * Most code should use the standard ActiveXComponent(String) contructor and + * not this factory method. This method exists for applications that need + * special behavior. Experimental in release 1.9.2. + *

+ * Factory that returns a Dispatch object wrapped around the result of a + * CoCreate() call. This differs from the standard constructor in that it + * throws no exceptions and returns null on failure. + *

+ * This will fail for any prog id with a ":" in it. + * + * @param pRequestedProgramId + * @return Dispatch pointer to the COM object or null if couldn't create + */ + public static ActiveXComponent createNewInstance(String pRequestedProgramId) { + ActiveXComponent mCreatedDispatch = null; + try { + mCreatedDispatch = new ActiveXComponent(); + mCreatedDispatch.coCreateInstance(pRequestedProgramId); + } catch (Exception e) { + mCreatedDispatch = null; + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("Unable to co-create instance of " + + pRequestedProgramId); + } + } + return mCreatedDispatch; + } - - /*============================================================ - * - * start of instance based calls to the COM layer - * =========================================================== - */ + /** + * Most code should use the standard ActiveXComponent(String) constructor and + * not this factory method. This method exists for applications that need + * special behavior. Experimental in release 1.9.2. + *

+ * Factory that returns a Dispatch wrapped around the result of a + * getActiveObject() call. This differs from the standard constructor in + * that it throws no exceptions and returns null on failure. + *

+ * This will fail for any prog id with a ":" in it + * + * @param pRequestedProgramId + * @return Dispatch pointer to a COM object or null if wasn't already + * running + */ + public static ActiveXComponent connectToActiveInstance( + String pRequestedProgramId) { + ActiveXComponent mCreatedDispatch = null; + try { + mCreatedDispatch = new ActiveXComponent(); + mCreatedDispatch.getActiveInstance(pRequestedProgramId); + } catch (Exception e) { + mCreatedDispatch = null; + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("Unable to attach to running instance of " + + pRequestedProgramId); + } + } + return mCreatedDispatch; + } - /** - * retrieves a property and returns it as a Variant - * @param propertyName - * @return variant value of property - */ - public Variant getProperty(String propertyName) - { - return Dispatch.get(this, propertyName); - } + /** + * @see com.jacob.com.Dispatch#finalize() + */ + protected void finalize() { + super.finalize(); + } - /** - * retrieves a property and returns it as an ActiveX component - * @param propertyName - * @return Dispatch representing the object under the property name - */ - public ActiveXComponent getPropertyAsComponent(String propertyName){ - return new ActiveXComponent(Dispatch.get(this,propertyName).toDispatch()); - - } - - /** - * retrieves a property and returns it as a Boolean - * @param propertyName property we are looking up - * @return boolean value of property - */ - public boolean getPropertyAsBoolean(String propertyName){ - return Dispatch.get(this, propertyName).getBoolean(); - } + /* + * ============================================================ + * + * start of instance based calls to the COM layer + * =========================================================== + */ - /** - * retrieves a property and returns it as a byte - * @param propertyName property we are looking up - * @return byte value of property - */ - public byte getPropertyAsByte(String propertyName){ - return Dispatch.get(this, propertyName).getByte(); - } + /** + * retrieves a property and returns it as a Variant + * + * @param propertyName + * @return variant value of property + */ + public Variant getProperty(String propertyName) { + return Dispatch.get(this, propertyName); + } - /** - * retrieves a property and returns it as a String - * @param propertyName - * @return String value of property - */ - public String getPropertyAsString(String propertyName){ - return Dispatch.get(this, propertyName).getString(); + /** + * retrieves a property and returns it as an ActiveX component + * + * @param propertyName + * @return Dispatch representing the object under the property name + */ + public ActiveXComponent getPropertyAsComponent(String propertyName) { + return new ActiveXComponent(Dispatch.get(this, propertyName) + .toDispatch()); - } - - /** - * retrieves a property and returns it as a int - * @param propertyName - * @return the property value as an int - */ - public int getPropertyAsInt(String propertyName){ - return Dispatch.get(this,propertyName).getInt(); - } + } - /** - * sets a property on this object - * @param propertyName property name - * @param arg variant value to be set - */ - public void setProperty(String propertyName, Variant arg) - { - Dispatch.put(this, propertyName, arg); - } + /** + * retrieves a property and returns it as a Boolean + * + * @param propertyName + * property we are looking up + * @return boolean value of property + */ + public boolean getPropertyAsBoolean(String propertyName) { + return Dispatch.get(this, propertyName).getBoolean(); + } - /** - * sets a property on this object - * @param propertyName property name - * @param arg variant value to be set - */ - public void setProperty(String propertyName, Dispatch arg) - { - Dispatch.put(this, propertyName, arg); - } + /** + * retrieves a property and returns it as a byte + * + * @param propertyName + * property we are looking up + * @return byte value of property + */ + public byte getPropertyAsByte(String propertyName) { + return Dispatch.get(this, propertyName).getByte(); + } - - /** - * sets a property to be the value of the string - * @param propertyName - * @param propertyValue - */ - public void setProperty(String propertyName, String propertyValue){ - this.setProperty(propertyName, new Variant(propertyValue)); - } + /** + * retrieves a property and returns it as a String + * + * @param propertyName + * @return String value of property + */ + public String getPropertyAsString(String propertyName) { + return Dispatch.get(this, propertyName).getString(); - /** - * sets a property as a boolean value - * @param propertyName - * @param propValue the boolean value we want the prop set to - */ - public void setProperty(String propertyName, boolean propValue){ - this.setProperty(propertyName, new Variant(propValue)); - } + } - /** - * sets a property as a boolean value - * @param propertyName - * @param propValue the boolean value we want the prop set to - */ - public void setProperty(String propertyName, byte propValue){ - this.setProperty(propertyName, new Variant(propValue)); - } + /** + * retrieves a property and returns it as a int + * + * @param propertyName + * @return the property value as an int + */ + public int getPropertyAsInt(String propertyName) { + return Dispatch.get(this, propertyName).getInt(); + } - /** - * sets the property as an int value - * @param propertyName - * @param propValue the int value we want the prop to be set to. - */ - public void setProperty(String propertyName, int propValue){ - this.setProperty(propertyName, new Variant(propValue)); - } + /** + * sets a property on this object + * + * @param propertyName + * property name + * @param arg + * variant value to be set + */ + public void setProperty(String propertyName, Variant arg) { + Dispatch.put(this, propertyName, arg); + } - /*------------------------------------------------------- - * Listener logging helpers - *------------------------------------------------------- - */ - - /** - * This boolean determines if callback events should be logged - */ - public static boolean shouldLogEvents = false; - - /** - * used by the doc and application listeners to get intelligent logging - * @param description event description - * @param args args passed in (variants) - * - */ - public void logCallbackEvent(String description, Variant[] args ) { - String argString = ""; - if (args!=null && ActiveXComponent.shouldLogEvents){ - if (args.length > 0){ - argString+=" args: "; - } - for ( int i = 0; i < args.length; i++){ - short argType = args[i].getvt(); - argString+=",["+i+"]"; - // break out the byref bits if they are on this - if ((argType & Variant.VariantByref) == Variant.VariantByref){ - // show the type and the fact that its byref - argString += "("+(args[i].getvt() & ~Variant.VariantByref)+ - "/"+Variant.VariantByref+")"; - } else { - // show the type - argString += "("+argType+")"; - } - argString += "="; - if (argType == Variant.VariantDispatch){ - Dispatch foo = (Dispatch)args[i].getDispatch(); - argString+=foo; - } else if ((argType & Variant.VariantBoolean) == - Variant.VariantBoolean){ - // do the boolean thing - if ((argType & Variant.VariantByref) == - Variant.VariantByref){ - // boolean by ref - argString += args[i].getBooleanRef(); - } else { - // boolean by value - argString += args[i].getBoolean(); - } - } else if ((argType & Variant.VariantString) == - Variant.VariantString){ - // do the string thing - if ((argType & Variant.VariantByref) == - Variant.VariantByref){ - // string by ref - argString += args[i].getStringRef(); - } else { - // string by value - argString += args[i].getString(); - } - } else { - argString+=args[i].toString(); - } - } - System.out.println(description +argString); - } - } - - /*============================================================== - * - * covers for dispatch call methods - *=============================================================*/ + /** + * sets a property on this object + * + * @param propertyName + * property name + * @param arg + * variant value to be set + */ + public void setProperty(String propertyName, Dispatch arg) { + Dispatch.put(this, propertyName, arg); + } - /** - * makes a dispatch call for the passed in action and no parameter - * @param callAction - * @return ActiveXComponent representing the results of the call - */ - public ActiveXComponent invokeGetComponent(String callAction){ - return new ActiveXComponent(invoke(callAction).toDispatch()); - } - - /** - * makes a dispatch call for the passed in action and single parameter - * @param callAction - * @param parameter - * @return ActiveXComponent representing the results of the call - */ - public ActiveXComponent invokeGetComponent(String callAction, - Variant parameter){ - return new ActiveXComponent(invoke(callAction, parameter).toDispatch()); - } - - /** - * makes a dispatch call for the passed in action and single parameter - * @param callAction - * @param parameter1 - * @param parameter2 - * @return ActiveXComponent representing the results of the call - */ - public ActiveXComponent invokeGetComponent(String callAction, - Variant parameter1, Variant parameter2){ - return new ActiveXComponent(invoke(callAction, - parameter1, parameter2).toDispatch()); - } - - /** - * makes a dispatch call for the passed in action and single parameter - * @param callAction - * @param parameter1 - * @param parameter2 - * @param parameter3 - * @return ActiveXComponent representing the results of the call - */ - public ActiveXComponent invokeGetComponent(String callAction, - Variant parameter1, - Variant parameter2, - Variant parameter3){ - return new ActiveXComponent(invoke(callAction, - parameter1, parameter2, parameter3).toDispatch()); - } - - /** - * makes a dispatch call for the passed in action and single parameter - * @param callAction - * @param parameter1 - * @param parameter2 - * @param parameter3 - * @param parameter4 - * @return ActiveXComponent representing the results of the call - */ - public ActiveXComponent invokeGetComponent(String callAction, - Variant parameter1, - Variant parameter2, - Variant parameter3, - Variant parameter4){ - return new ActiveXComponent(invoke(callAction, - parameter1, parameter2, parameter3, parameter4) - .toDispatch()); - } - - /** - * invokes a single parameter call on this dispatch - * that returns no value - * @param actionCommand - * @param parameter - * @return a Variant but that may be null for some calls - */ - public Variant invoke(String actionCommand, String parameter){ - return Dispatch.call(this, actionCommand, parameter); - } - - /** - * makes a dispatch call to the passed in action with a single boolean parameter - * @param actionCommand - * @param parameter - * @return Variant result - */ - public Variant invoke(String actionCommand, boolean parameter){ - return Dispatch.call(this, actionCommand, new Variant(parameter)); - } + /** + * sets a property to be the value of the string + * + * @param propertyName + * @param propertyValue + */ + public void setProperty(String propertyName, String propertyValue) { + this.setProperty(propertyName, new Variant(propertyValue)); + } - /** - * makes a dispatch call to the passed in action with a single int parameter - * @param actionCommand - * @param parameter - * @return Variant result of the invoke (Dispatch.call) - */ - public Variant invoke(String actionCommand, int parameter){ - return Dispatch.call(this, actionCommand, new Variant(parameter)); - } - - /** - * makes a dispatch call to the passed in action with a string and integer parameter - * (this was put in for some application) - * @param actionCommand - * @param parameter1 - * @param parameter2 - * @return Variant result - */ - public Variant invoke(String actionCommand, String parameter1, int parameter2){ - return Dispatch.call(this, actionCommand, parameter1, new Variant(parameter2)); - } + /** + * sets a property as a boolean value + * + * @param propertyName + * @param propValue + * the boolean value we want the prop set to + */ + public void setProperty(String propertyName, boolean propValue) { + this.setProperty(propertyName, new Variant(propValue)); + } - /** - * makes a dispatch call to the passed in action with two - * integer parameters - * (this was put in for some application) - * @param actionCommand - * @param parameter1 - * @param parameter2 - * @return a Variant but that may be null for some calls - */ - public Variant invoke(String actionCommand, - int parameter1, int parameter2){ - return Dispatch.call(this, actionCommand, - new Variant(parameter1),new Variant(parameter2)); - } - /** - * makes a dispatch call for the passed in action and single parameter - * @param callAction - * @param parameter - * @return a Variant but that may be null for some calls - */ - public Variant invoke(String callAction, Variant parameter){ - return Dispatch.call(this,callAction, parameter); - } - - /** - * makes a dispatch call for the passed in action and two parameter - * @param callAction - * @param parameter1 - * @param parameter2 - * @return a Variant but that may be null for some calls - */ - public Variant invoke(String callAction, - Variant parameter1, - Variant parameter2){ - return Dispatch.call(this,callAction, parameter1,parameter2); - } - - /** - * makes a dispatch call for the passed in action and two parameter - * @param callAction - * @param parameter1 - * @param parameter2 - * @param parameter3 - * @return Variant result data - */ - public Variant invoke(String callAction, - Variant parameter1, - Variant parameter2, - Variant parameter3){ - return Dispatch.call(this,callAction, - parameter1, parameter2, parameter3); - } + /** + * sets a property as a boolean value + * + * @param propertyName + * @param propValue + * the boolean value we want the prop set to + */ + public void setProperty(String propertyName, byte propValue) { + this.setProperty(propertyName, new Variant(propValue)); + } + /** + * sets the property as an int value + * + * @param propertyName + * @param propValue + * the int value we want the prop to be set to. + */ + public void setProperty(String propertyName, int propValue) { + this.setProperty(propertyName, new Variant(propValue)); + } - /** - * calls call() with 4 variant parameters - * @param callAction - * @param parameter1 - * @param parameter2 - * @param parameter3 - * @param parameter4 - * @return Variant result data - */ - public Variant invoke(String callAction, - Variant parameter1, - Variant parameter2, - Variant parameter3, - Variant parameter4){ - return Dispatch.call(this,callAction, - parameter1, parameter2, parameter3, parameter4); - } - - - /** - * makes a dispatch call for the passed in action and no parameter - * @param callAction - * @return a Variant but that may be null for some calls - */ - public Variant invoke(String callAction){ - return Dispatch.call(this,callAction); - } - - /** - * This is really a cover for call(String,Variant[]) that should be eliminated - * call with a variable number of args mainly used for quit. - * @param name - * @param args - * @return Variant returned by the invoke (Dispatch.callN) - */ - public Variant invoke(String name, Variant[] args) - { - return Dispatch.callN(this, name, args); - } + /*------------------------------------------------------- + * Listener logging helpers + *------------------------------------------------------- + */ + + /** + * This boolean determines if callback events should be logged + */ + public static boolean shouldLogEvents = false; + + /** + * used by the doc and application listeners to get intelligent logging + * + * @param description + * event description + * @param args + * args passed in (variants) + * + */ + public void logCallbackEvent(String description, Variant[] args) { + String argString = ""; + if (args != null && ActiveXComponent.shouldLogEvents) { + if (args.length > 0) { + argString += " args: "; + } + for (int i = 0; i < args.length; i++) { + short argType = args[i].getvt(); + argString += ",[" + i + "]"; + // break out the byref bits if they are on this + if ((argType & Variant.VariantByref) == Variant.VariantByref) { + // show the type and the fact that its byref + argString += "(" + + (args[i].getvt() & ~Variant.VariantByref) + "/" + + Variant.VariantByref + ")"; + } else { + // show the type + argString += "(" + argType + ")"; + } + argString += "="; + if (argType == Variant.VariantDispatch) { + Dispatch foo = (args[i].getDispatch()); + argString += foo; + } else if ((argType & Variant.VariantBoolean) == Variant.VariantBoolean) { + // do the boolean thing + if ((argType & Variant.VariantByref) == Variant.VariantByref) { + // boolean by ref + argString += args[i].getBooleanRef(); + } else { + // boolean by value + argString += args[i].getBoolean(); + } + } else if ((argType & Variant.VariantString) == Variant.VariantString) { + // do the string thing + if ((argType & Variant.VariantByref) == Variant.VariantByref) { + // string by ref + argString += args[i].getStringRef(); + } else { + // string by value + argString += args[i].getString(); + } + } else { + argString += args[i].toString(); + } + } + System.out.println(description + argString); + } + } + + /* + * ============================================================== + * + * covers for dispatch call methods + * ============================================================= + */ + + /** + * makes a dispatch call for the passed in action and no parameter + * + * @param callAction + * @return ActiveXComponent representing the results of the call + */ + public ActiveXComponent invokeGetComponent(String callAction) { + return new ActiveXComponent(invoke(callAction).toDispatch()); + } + + /** + * makes a dispatch call for the passed in action and single parameter + * + * @param callAction + * @param parameter + * @return ActiveXComponent representing the results of the call + */ + public ActiveXComponent invokeGetComponent(String callAction, + Variant parameter) { + return new ActiveXComponent(invoke(callAction, parameter).toDispatch()); + } + + /** + * makes a dispatch call for the passed in action and single parameter + * + * @param callAction + * @param parameter1 + * @param parameter2 + * @return ActiveXComponent representing the results of the call + */ + public ActiveXComponent invokeGetComponent(String callAction, + Variant parameter1, Variant parameter2) { + return new ActiveXComponent(invoke(callAction, parameter1, parameter2) + .toDispatch()); + } + + /** + * makes a dispatch call for the passed in action and single parameter + * + * @param callAction + * @param parameter1 + * @param parameter2 + * @param parameter3 + * @return ActiveXComponent representing the results of the call + */ + public ActiveXComponent invokeGetComponent(String callAction, + Variant parameter1, Variant parameter2, Variant parameter3) { + return new ActiveXComponent(invoke(callAction, parameter1, parameter2, + parameter3).toDispatch()); + } + + /** + * makes a dispatch call for the passed in action and single parameter + * + * @param callAction + * @param parameter1 + * @param parameter2 + * @param parameter3 + * @param parameter4 + * @return ActiveXComponent representing the results of the call + */ + public ActiveXComponent invokeGetComponent(String callAction, + Variant parameter1, Variant parameter2, Variant parameter3, + Variant parameter4) { + return new ActiveXComponent(invoke(callAction, parameter1, parameter2, + parameter3, parameter4).toDispatch()); + } + + /** + * invokes a single parameter call on this dispatch that returns no value + * + * @param actionCommand + * @param parameter + * @return a Variant but that may be null for some calls + */ + public Variant invoke(String actionCommand, String parameter) { + return Dispatch.call(this, actionCommand, parameter); + } + + /** + * makes a dispatch call to the passed in action with a single boolean + * parameter + * + * @param actionCommand + * @param parameter + * @return Variant result + */ + public Variant invoke(String actionCommand, boolean parameter) { + return Dispatch.call(this, actionCommand, new Variant(parameter)); + } + + /** + * makes a dispatch call to the passed in action with a single int parameter + * + * @param actionCommand + * @param parameter + * @return Variant result of the invoke (Dispatch.call) + */ + public Variant invoke(String actionCommand, int parameter) { + return Dispatch.call(this, actionCommand, new Variant(parameter)); + } + + /** + * makes a dispatch call to the passed in action with a string and integer + * parameter (this was put in for some application) + * + * @param actionCommand + * @param parameter1 + * @param parameter2 + * @return Variant result + */ + public Variant invoke(String actionCommand, String parameter1, + int parameter2) { + return Dispatch.call(this, actionCommand, parameter1, new Variant( + parameter2)); + } + + /** + * makes a dispatch call to the passed in action with two integer parameters + * (this was put in for some application) + * + * @param actionCommand + * @param parameter1 + * @param parameter2 + * @return a Variant but that may be null for some calls + */ + public Variant invoke(String actionCommand, int parameter1, int parameter2) { + return Dispatch.call(this, actionCommand, new Variant(parameter1), + new Variant(parameter2)); + } + + /** + * makes a dispatch call for the passed in action and single parameter + * + * @param callAction + * @param parameter + * @return a Variant but that may be null for some calls + */ + public Variant invoke(String callAction, Variant parameter) { + return Dispatch.call(this, callAction, parameter); + } + + /** + * makes a dispatch call for the passed in action and two parameter + * + * @param callAction + * @param parameter1 + * @param parameter2 + * @return a Variant but that may be null for some calls + */ + public Variant invoke(String callAction, Variant parameter1, + Variant parameter2) { + return Dispatch.call(this, callAction, parameter1, parameter2); + } + + /** + * makes a dispatch call for the passed in action and two parameter + * + * @param callAction + * @param parameter1 + * @param parameter2 + * @param parameter3 + * @return Variant result data + */ + public Variant invoke(String callAction, Variant parameter1, + Variant parameter2, Variant parameter3) { + return Dispatch.call(this, callAction, parameter1, parameter2, + parameter3); + } + + /** + * calls call() with 4 variant parameters + * + * @param callAction + * @param parameter1 + * @param parameter2 + * @param parameter3 + * @param parameter4 + * @return Variant result data + */ + public Variant invoke(String callAction, Variant parameter1, + Variant parameter2, Variant parameter3, Variant parameter4) { + return Dispatch.call(this, callAction, parameter1, parameter2, + parameter3, parameter4); + } + + /** + * makes a dispatch call for the passed in action and no parameter + * + * @param callAction + * @return a Variant but that may be null for some calls + */ + public Variant invoke(String callAction) { + return Dispatch.call(this, callAction); + } + + /** + * This is really a cover for call(String,Variant[]) that should be + * eliminated call with a variable number of args mainly used for quit. + * + * @param name + * @param args + * @return Variant returned by the invoke (Dispatch.callN) + */ + public Variant invoke(String name, Variant[] args) { + return Dispatch.callN(this, name, args); + } - } \ No newline at end of file diff --git a/src/com/jacob/activeX/ActiveXDispatchEvents.java b/src/com/jacob/activeX/ActiveXDispatchEvents.java index a91d686..16bb649 100644 --- a/src/com/jacob/activeX/ActiveXDispatchEvents.java +++ b/src/com/jacob/activeX/ActiveXDispatchEvents.java @@ -26,67 +26,78 @@ import com.jacob.com.InvocationProxy; /** * RELEASE 1.12 EXPERIMENTAL. *

- * Use this exactly like the DispatchEvents class. This class plugs in - * an ActiveXInvocationProxy instead of an InvocationProxy. It is the - * ActiveXInvocationProxy that implements the reflection calls and invoke - * the found java event callbacks. See ActiveXInvocationProxy for details. + * Use this exactly like the DispatchEvents class. This class plugs in an + * ActiveXInvocationProxy instead of an InvocationProxy. It is the + * ActiveXInvocationProxy that implements the reflection calls and invoke the + * found java event callbacks. See ActiveXInvocationProxy for details. + * * - * */ public class ActiveXDispatchEvents extends DispatchEvents { - /** - * This is the most commonly used constructor. - *

- * Creates the event callback linkage between the the - * MS program represented by the Dispatch object and the - * Java object that will receive the callback. - * @param sourceOfEvent Dispatch object who's MS app will generate callbacks - * @param eventSink Java object that wants to receive the events - */ - public ActiveXDispatchEvents(Dispatch sourceOfEvent, Object eventSink) { - super(sourceOfEvent, eventSink, null ); - } + /** + * This is the most commonly used constructor. + *

+ * Creates the event callback linkage between the the MS program represented + * by the Dispatch object and the Java object that will receive the + * callback. + * + * @param sourceOfEvent + * Dispatch object who's MS app will generate callbacks + * @param eventSink + * Java object that wants to receive the events + */ + public ActiveXDispatchEvents(Dispatch sourceOfEvent, Object eventSink) { + super(sourceOfEvent, eventSink, null); + } - /** - * None of the samples use this constructor. - *

- * Creates the event callback linkage between the the - * MS program represented by the Dispatch object and the - * Java object that will receive the callback. - * @param sourceOfEvent Dispatch object who's MS app will generate callbacks - * @param eventSink Java object that wants to receive the events - * @param progId ??? - */ - public ActiveXDispatchEvents(Dispatch sourceOfEvent, Object eventSink, String progId) { - super(sourceOfEvent, eventSink, progId, null ); - } + /** + * None of the samples use this constructor. + *

+ * Creates the event callback linkage between the the MS program represented + * by the Dispatch object and the Java object that will receive the + * callback. + * + * @param sourceOfEvent + * Dispatch object who's MS app will generate callbacks + * @param eventSink + * Java object that wants to receive the events + * @param progId + * ??? + */ + public ActiveXDispatchEvents(Dispatch sourceOfEvent, Object eventSink, + String progId) { + super(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. - *

-     * >ActiveXDispatchEvents de = 
-     * 			new ActiveXDispatchEvents(someDispatch,someEventHAndler,
-     * 				"Excel.Application",
-     * 				"C:\\Program Files\\Microsoft Office\\OFFICE11\\EXCEL.EXE");
-     *
-     * @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 ActiveXDispatchEvents(Dispatch sourceOfEvent, Object eventSink, String progId, String typeLib)
-    {
-    	super(sourceOfEvent, eventSink, progId, typeLib);
-    }
+	/**
+	 * Creates the event callback linkage between the the MS program represented
+	 * by the Dispatch object and the Java object that will receive the
+	 * callback.
+	 * 
+	 * 
+	 * >ActiveXDispatchEvents de = 
+	 * 			new ActiveXDispatchEvents(someDispatch,someEventHAndler,
+	 * 				"Excel.Application",
+	 * 				"C:\\Program Files\\Microsoft Office\\OFFICE11\\EXCEL.EXE");
+	 * 
+	 * @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 ActiveXDispatchEvents(Dispatch sourceOfEvent, Object eventSink,
+			String progId, String typeLib) {
+		super(sourceOfEvent, eventSink, progId, typeLib);
+	}
 
-    /*
-     * (non-Javadoc)
-     * @see com.jacob.com.DispatchEvents#getInvocationProxy(java.lang.Object)
-     */
-	protected InvocationProxy getInvocationProxy(Object pTargetObject){
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see com.jacob.com.DispatchEvents#getInvocationProxy(java.lang.Object)
+	 */
+	protected InvocationProxy getInvocationProxy(Object pTargetObject) {
 		InvocationProxy newProxy = new ActiveXInvocationProxy();
 		newProxy.setTarget(pTargetObject);
 		return newProxy;
diff --git a/src/com/jacob/activeX/ActiveXInvocationProxy.java b/src/com/jacob/activeX/ActiveXInvocationProxy.java
index 59f8e9f..94c4f31 100644
--- a/src/com/jacob/activeX/ActiveXInvocationProxy.java
+++ b/src/com/jacob/activeX/ActiveXInvocationProxy.java
@@ -29,63 +29,70 @@ import com.jacob.com.Variant;
 /**
  * RELEASE 1.12 EXPERIMENTAL.
  * 

- * This class that lets event handlers receive events with all java - * objects as parameters. The standard Jacob event methods all accept an array of - * Variant objects. When using this class, you can set up your event methods - * as regular java methods with the correct number of parameters of the correct - * java type. This does NOT work for any event that wishes to accept a call - * back and modify the calling parameters to tell windows what to do. An example - * is when an event lets the receiver cancel the action by setting a boolean flag - * to false. The java objects cannot be modified and their values will not be passed - * back into the originating Variants even if they could be modified. + * This class that lets event handlers receive events with all java objects as + * parameters. The standard Jacob event methods all accept an array of Variant + * objects. When using this class, you can set up your event methods as regular + * java methods with the correct number of parameters of the correct java type. + * This does NOT work for any event that wishes to accept a call back and modify + * the calling parameters to tell windows what to do. An example is when an + * event lets the receiver cancel the action by setting a boolean flag to false. + * The java objects cannot be modified and their values will not be passed back + * into the originating Variants even if they could be modified. *

* This class acts as a proxy between the windows event callback mechanism and - * the Java classes that are looking for events. It assumes that - * all of the Java classes that are looking for events implement methods with the - * same names as the windows events and that the implemented methods native - * java objects of the type and order that match the windows documentation. - * The methods can return void or a Variant that - * will be returned to the calling layer. All Event methods that will be - * recognized by InvocationProxyAllEvents have the signature - * - * void eventMethodName(Object,Object...) - * or - * Object eventMethodName(Object,Object...) + * the Java classes that are looking for events. It assumes that all of the Java + * classes that are looking for events implement methods with the same names as + * the windows events and that the implemented methods native java objects of + * the type and order that match the windows documentation. The methods can + * return void or a Variant that will be returned to the calling layer. All + * Event methods that will be recognized by InvocationProxyAllEvents have the + * signature + * + * void eventMethodName(Object,Object...) or + * Object eventMethodName(Object,Object...) */ public class ActiveXInvocationProxy extends InvocationProxy { /* * (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[]) { - Variant mVariantToBeReturned = null; - if (mTargetObject == null){ - // structured programming guidlines say this return should not be up here + Variant mVariantToBeReturned = null; + if (mTargetObject == null) { + // structured programming guidlines say this return should not be up + // here return null; } Class targetClass = mTargetObject.getClass(); - if (methodName == null){ - throw new IllegalArgumentException("InvocationProxy: missing method name"); + if (methodName == null) { + throw new IllegalArgumentException( + "InvocationProxy: missing method name"); } - if (targetParameters == null){ - throw new IllegalArgumentException("InvocationProxy: missing Variant parameters"); + if (targetParameters == null) { + throw new IllegalArgumentException( + "InvocationProxy: missing Variant parameters"); } try { Method targetMethod; Object parametersAsJavaObjects[] = getParametersAsJavaObjects(targetParameters); - Class parametersAsJavaClasses[] = getParametersAsJavaClasses(parametersAsJavaObjects); - targetMethod = targetClass.getMethod(methodName, parametersAsJavaClasses); - if (targetMethod != null){ + Class parametersAsJavaClasses[] = getParametersAsJavaClasses(parametersAsJavaObjects); + targetMethod = targetClass.getMethod(methodName, + parametersAsJavaClasses); + if (targetMethod != null) { // 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 Object mReturnedByInvocation = null; - mReturnedByInvocation = - targetMethod.invoke(mTargetObject,parametersAsJavaObjects); - if (mReturnedByInvocation == null){ + mReturnedByInvocation = targetMethod.invoke(mTargetObject, + parametersAsJavaObjects); + if (mReturnedByInvocation == null) { mVariantToBeReturned = null; - } else if (!(mReturnedByInvocation instanceof Variant)){ + } else if (!(mReturnedByInvocation instanceof Variant)) { mVariantToBeReturned = new Variant(mReturnedByInvocation); } else { mVariantToBeReturned = (Variant) mReturnedByInvocation; @@ -95,11 +102,13 @@ public class ActiveXInvocationProxy extends InvocationProxy { // what causes this exception? e.printStackTrace(); } 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) { - // 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 - + ": "+e.toString()); + // 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 + ": " + + e.toString()); oneWeShouldToss.printStackTrace(); } catch (IllegalAccessException e) { // can't access the method on the target instance for some reason @@ -109,23 +118,27 @@ public class ActiveXInvocationProxy extends InvocationProxy { e.printStackTrace(); } 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 * @return */ + @SuppressWarnings("unchecked") private Class[] getParametersAsJavaClasses(Object[] parametersAsJavaObjects) { - if (parametersAsJavaObjects == null){ - throw new IllegalArgumentException("This only works with an array of parameters"); + if (parametersAsJavaObjects == null) { + throw new IllegalArgumentException( + "This only works with an array of parameters"); } int numParameters = parametersAsJavaObjects.length; Class parametersAsJavaClasses[] = new Class[numParameters]; - for ( int parameterIndex = 0 ; parameterIndex < numParameters; parameterIndex++){ + for (int parameterIndex = 0; parameterIndex < numParameters; parameterIndex++) { Object oneParameterObject = parametersAsJavaObjects[parameterIndex]; - if (oneParameterObject == null){ + if (oneParameterObject == null) { parametersAsJavaClasses[parameterIndex] = null; } else { Class oneParameterClass = oneParameterObject.getClass(); @@ -137,31 +150,34 @@ public class ActiveXInvocationProxy extends InvocationProxy { /** * converts an array of Variants to their associated Java types + * * @param targetParameters * @return */ private Object[] getParametersAsJavaObjects(Variant[] targetParameters) { - if (targetParameters == null){ - throw new IllegalArgumentException("This only works with an array of parameters"); + if (targetParameters == null) { + throw new IllegalArgumentException( + "This only works with an array of parameters"); } int numParameters = targetParameters.length; Object parametersAsJavaObjects[] = new Object[numParameters]; - for ( int parameterIndex = 0 ; parameterIndex < numParameters; parameterIndex++){ + for (int parameterIndex = 0; parameterIndex < numParameters; parameterIndex++) { Variant oneParameterObject = targetParameters[parameterIndex]; - if (oneParameterObject == null){ + if (oneParameterObject == null) { parametersAsJavaObjects[parameterIndex] = null; } else { try { - parametersAsJavaObjects[parameterIndex] = oneParameterObject.toJavaObject(); - } catch (NotImplementedException nie){ - throw new IllegalArgumentException("Can't convert parameter "+parameterIndex+ - " type "+oneParameterObject.getvt() - +" to java object: "+nie.getMessage()); + parametersAsJavaObjects[parameterIndex] = oneParameterObject + .toJavaObject(); + } catch (NotImplementedException nie) { + throw new IllegalArgumentException( + "Can't convert parameter " + parameterIndex + + " type " + oneParameterObject.getvt() + + " to java object: " + nie.getMessage()); } } } return parametersAsJavaObjects; } - } diff --git a/src/com/jacob/com/ComException.java b/src/com/jacob/com/ComException.java index f3275cb..8632577 100644 --- a/src/com/jacob/com/ComException.java +++ b/src/com/jacob/com/ComException.java @@ -22,111 +22,120 @@ package com.jacob.com; /** * Standard exception thrown by com jni code when there is a problem */ -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; +public abstract class ComException extends JacobException { - /** - * constructor - * - */ - public ComException() { - super(); - } + /** + * 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 with error code? - * - * @param newHr ?? - */ - public ComException(int newHr) { - super(); - this.hr = newHr; - } + /** + * constructor + * + */ + public ComException() { + super(); + } - /** - * @param newHr - * @param description - */ - public ComException(int newHr, String description) { - super(description); - this.hr = newHr; - } + /** + * constructor with error code? + * + * @param newHr ?? + */ + public ComException(int newHr) { + super(); + this.hr = newHr; + } - /** - * @param newHr - * @param source - * @param helpFile - * @param helpContext - */ - public ComException(int newHr, String source, String helpFile, - int helpContext) { - super(); - this.hr = newHr; - m_source = source; - m_helpFile = helpFile; - m_helpContext = helpContext; - } + /** + * @param newHr + * @param description + */ + public ComException(int newHr, String description) { + super(description); + this.hr = newHr; + } - /** - * @param newHr - * @param description - * @param source - * @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; - } + /** + * @param newHr + * @param source + * @param helpFile + * @param helpContext + */ + public ComException(int newHr, String source, String helpFile, + int helpContext) { + super(); + this.hr = newHr; + m_source = source; + m_helpFile = helpFile; + m_helpContext = helpContext; + } - /** - * @param description - */ - public ComException(String description) { - super(description); - } + /** + * @param newHr + * @param description + * @param source + * @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 - */ - // Methods - public int getHelpContext() { - return m_helpContext; - } + /** + * @param description + */ + public ComException(String description) { + super(description); + } - /** - * @return String ??? help file - */ - public String getHelpFile() { - return m_helpFile; - } + /** + * @return int representation of the help context + */ + // Methods + public int getHelpContext() { + return m_helpContext; + } - /** - * @return int hr result ?? - */ - public int getHResult() { - return hr; - } + /** + * @return String ??? help file + */ + public String getHelpFile() { + return m_helpFile; + } - /** - * @return String source ?? - */ - public String getSource() { - return m_source; - } + /** + * @return int hr result ?? + */ + public int getHResult() { + return hr; + } + + /** + * @return String source ?? + */ + public String getSource() { + return m_source; + } } \ No newline at end of file diff --git a/src/com/jacob/com/ComFailException.java b/src/com/jacob/com/ComFailException.java index f19b83b..20ce1a8 100644 --- a/src/com/jacob/com/ComFailException.java +++ b/src/com/jacob/com/ComFailException.java @@ -23,63 +23,66 @@ package com.jacob.com; * COM Fail Exception class raised when there is a problem */ public class ComFailException extends ComException { - /** + /** * eclipse generated to get rid of a wanring */ private static final long serialVersionUID = -266047261992987700L; /** * Constructor - * @param hrNew - */ - public ComFailException(int hrNew) { - super(hrNew); - } + * + * @param hrNew + */ + public ComFailException(int hrNew) { + super(hrNew); + } - /** - * Constructor - * @param hrNew - * @param message - */ - public ComFailException(int hrNew, String message) { - super(hrNew, message); - } + /** + * Constructor + * + * @param hrNew + * @param message + */ + public ComFailException(int hrNew, String message) { + super(hrNew, message); + } - /** - * @param hrNew - * @param source - * @param helpFile - * @param helpContext - */ - public ComFailException(int hrNew, String source, String helpFile, - int helpContext) { - super(hrNew, source, helpFile, helpContext); - } + /** + * @param hrNew + * @param source + * @param helpFile + * @param helpContext + */ + public ComFailException(int hrNew, String source, String helpFile, + int helpContext) { + super(hrNew, source, helpFile, helpContext); + } - /** - * Constructor - * @param hrNew - * @param description - * @param source - * @param helpFile - * @param helpContext - */ - public ComFailException(int hrNew, String description, String source, - String helpFile, int helpContext) { - super(hrNew, description, source, helpFile, helpContext); - } + /** + * Constructor + * + * @param hrNew + * @param description + * @param source + * @param helpFile + * @param helpContext + */ + public ComFailException(int hrNew, String description, String source, + String helpFile, int helpContext) { + super(hrNew, description, source, helpFile, helpContext); + } - /** - * No argument Constructor - */ - public ComFailException() { - super(); - } + /** + * No argument Constructor + */ + public ComFailException() { + super(); + } - /** - * @param message - */ - public ComFailException(String message) { - super(message); - } + /** + * @param message + */ + public ComFailException(String message) { + super(message); + } } \ No newline at end of file diff --git a/src/com/jacob/com/ComThread.java b/src/com/jacob/com/ComThread.java index e4c1c67..aeee598 100644 --- a/src/com/jacob/com/ComThread.java +++ b/src/com/jacob/com/ComThread.java @@ -20,135 +20,150 @@ package com.jacob.com; /** - * Represents a COM level thread - * This is an abstract class because all the methods are static - * and no instances are ever created. + * Represents a COM level thread This is an abstract class because all the + * methods are static and no instances are ever created. */ 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 haveSTA - */ - public static boolean haveSTA = false; + /** + * Comment for haveSTA + */ + public static boolean haveSTA = false; - /** - * Comment for mainSTA - */ - public static MainSTA mainSTA = null; + /** + * Comment for mainSTA + */ + public static MainSTA mainSTA = null; - /** - * Initialize the current java thread to be part of the Multi-threaded COM - * Apartment - */ - public static synchronized void InitMTA() { - InitMTA(false); - } + /** + * Initialize the current java thread to be part of the Multi-threaded COM + * Apartment + */ + public static synchronized void InitMTA() { + InitMTA(false); + } - /** - * Initialize the current java thread to be an STA - */ - public static synchronized void InitSTA() { - InitSTA(false); - } + /** + * Initialize the current java thread to be an STA + */ + public static synchronized void InitSTA() { + InitSTA(false); + } - /** - * Initialize the current java thread to be part of the Multi-threaded COM - * Apartment, if createMainSTA is true, create a separate MainSTA thread - * that will house all Apartment Threaded components - * @param createMainSTA - */ - public static synchronized void InitMTA(boolean createMainSTA) { - Init(createMainSTA, MTA); - } + /** + * Initialize the current java thread to be part of the Multi-threaded COM + * Apartment, if createMainSTA is true, create a separate MainSTA thread + * that will house all Apartment Threaded components + * + * @param createMainSTA + */ + public static synchronized void InitMTA(boolean createMainSTA) { + Init(createMainSTA, MTA); + } - /** - * Initialize the current java thread to be an STA COM Apartment, if - * createMainSTA is true, create a separate MainSTA thread that will house - * all Apartment Threaded components - * @param createMainSTA - */ - public static synchronized void InitSTA(boolean createMainSTA) { - Init(createMainSTA, STA); - } + /** + * Initialize the current java thread to be an STA COM Apartment, if + * createMainSTA is true, create a separate MainSTA thread that will house + * all Apartment Threaded components + * + * @param createMainSTA + */ + public static synchronized void InitSTA(boolean createMainSTA) { + Init(createMainSTA, STA); + } - /** - * - */ - public static synchronized void startMainSTA() { - mainSTA = new MainSTA(); - haveSTA = true; - } + /** + * + */ + public static synchronized void startMainSTA() { + mainSTA = new MainSTA(); + haveSTA = true; + } - /** - * - */ - public static synchronized void quitMainSTA() { - if (mainSTA != null) - mainSTA.quit(); - } + /** + * + */ + public static synchronized void quitMainSTA() { + if (mainSTA != null) + mainSTA.quit(); + } - /** - * Initialize the current java thread to be part of the MTA/STA COM - * Apartment - * @param createMainSTA - * @param mode - */ - public static synchronized void Init(boolean createMainSTA, int mode) { - if (createMainSTA && !haveSTA) { - // if the current thread is going to be in the MTA and there - // is no STA thread yet, then create a main STA thread - // to avoid COM creating its own - startMainSTA(); - } - if (JacobObject.isDebugEnabled()){JacobObject.debug("ComThread: before Init: "+mode);} - doCoInitialize(mode); - if (JacobObject.isDebugEnabled()){JacobObject.debug("ComThread: after Init: "+mode);} - ROT.addThread(); - if (JacobObject.isDebugEnabled()){JacobObject.debug("ComThread: after ROT.addThread: "+mode); } - } + /** + * Initialize the current java thread to be part of the MTA/STA COM + * Apartment + * + * @param createMainSTA + * @param mode + */ + public static synchronized void Init(boolean createMainSTA, int mode) { + if (createMainSTA && !haveSTA) { + // if the current thread is going to be in the MTA and there + // is no STA thread yet, then create a main STA thread + // to avoid COM creating its own + startMainSTA(); + } + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("ComThread: before Init: " + 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 - */ - public static synchronized void Release() { - if (JacobObject.isDebugEnabled()){JacobObject.debug("ComThread: before clearObjects"); } - ROT.clearObjects(); - if (JacobObject.isDebugEnabled()){JacobObject.debug("ComThread: before UnInit"); } - doCoUninitialize(); - if (JacobObject.isDebugEnabled()){JacobObject.debug("ComThread: after UnInit"); } - } - - /** - * @deprecated the java model leave the responsibility of clearing up objects - * to the Garbage Collector. Our programming model should not require that the - * 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); - } + /** + * Call CoUninitialize to release this java thread from COM + */ + public static synchronized void Release() { + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("ComThread: before clearObjects"); + } + ROT.clearObjects(); + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("ComThread: before UnInit"); + } + doCoUninitialize(); + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("ComThread: after UnInit"); + } + } - /** - * @param threadModel - */ - public static native void doCoInitialize(int threadModel); + /** + * @deprecated the java model leave the responsibility of clearing up + * objects to the Garbage Collector. Our programming model + * 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); + } - /** - * - */ - public static native void doCoUninitialize(); + /** + * @param threadModel + */ + 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. - */ - static { - LibraryLoader.loadJacobLibrary(); - } + /** + * + */ + public static native void doCoUninitialize(); + + /** + * 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(); + } } \ No newline at end of file diff --git a/src/com/jacob/com/Currency.java b/src/com/jacob/com/Currency.java new file mode 100644 index 0000000..749506c --- /dev/null +++ b/src/com/jacob/com/Currency.java @@ -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. + *

+ * 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; + } + } +} diff --git a/src/com/jacob/com/DateUtilities.java b/src/com/jacob/com/DateUtilities.java index b74b76e..195ba33 100644 --- a/src/com/jacob/com/DateUtilities.java +++ b/src/com/jacob/com/DateUtilities.java @@ -24,29 +24,30 @@ import java.util.Date; /** * java / windows date conversion utilities + * * @author joe - * + * */ public class DateUtilities { /** * converts a windows time to a Java Date Object + * * @param comTime * @return Date object representing the windows time as specified in comTime */ - static public Date convertWindowsTimeToDate(double comTime){ - return new Date(convertWindowsTimeToMilliseconds (comTime)); + static public Date convertWindowsTimeToDate(double comTime) { + return new Date(convertWindowsTimeToMilliseconds(comTime)); } - - /** - * Convert a COM time from functions Date(), Time(), Now() to a - * Java time (milliseconds). Visual Basic time values are based to - * 30.12.1899, Java time values are based to 1.1.1970 (= 0 - * milliseconds). The difference is added to the Visual Basic value to - * get the corresponding Java value. The Visual Basic double value - * reads: .<1 day percentage - * fraction>, e.g. "38100.6453" means: 38100 days since 30.12.1899 plus - * (24 hours * 0.6453). Example usage: + + /** + * Convert a COM time from functions Date(), Time(), Now() to a Java time + * (milliseconds). Visual Basic time values are based to 30.12.1899, Java + * time values are based to 1.1.1970 (= 0 milliseconds). The difference is + * added to the Visual Basic value to get the corresponding Java value. The + * Visual Basic double value reads: .<1 + * day percentage fraction>, e.g. "38100.6453" means: 38100 days since + * 30.12.1899 plus (24 hours * 0.6453). Example usage: * Date javaDate = new Date(toMilliseconds (vbDate));. * * @param comTime @@ -68,19 +69,20 @@ public class DateUtilities { }// convertWindowsTimeToMilliseconds() /** - * converts a java date to a windows time object - * (is this timezone safe?) + * converts a java date to a windows time object (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 */ - static public double convertDateToWindowsTime(Date javaDate){ - if (javaDate == null){ - throw new IllegalArgumentException("cannot convert null to windows time"); + static public double convertDateToWindowsTime(Date javaDate) { + if (javaDate == null) { + throw new IllegalArgumentException( + "cannot convert null to windows time"); } return convertMillisecondsToWindowsTime(javaDate.getTime()); } - + /** * Convert a Java time to a COM time. * @@ -99,5 +101,5 @@ public class DateUtilities { result = (milliseconds / 86400000D) + 25569D; return result; - }//convertMillisecondsToWindowsTime() + }// convertMillisecondsToWindowsTime() } diff --git a/src/com/jacob/com/Dispatch.java b/src/com/jacob/com/Dispatch.java index bde922d..0af2959 100644 --- a/src/com/jacob/com/Dispatch.java +++ b/src/com/jacob/com/Dispatch.java @@ -19,1345 +19,1300 @@ */ package com.jacob.com; -import java.lang.reflect.Array; -import java.util.Date; - /** - * Object represents MS level dispatch object. - * Each instance of this points at some data structure on the - * MS windows side. + * Object represents MS level dispatch object. Each instance of this points at + * some data structure on the MS windows side. * * - *

You're going to live here a lot + *

+ * You're going to live here a lot */ -public class Dispatch extends JacobObject -{ - public static final int LOCALE_SYSTEM_DEFAULT = 2048; - public static final int Method = 1; - public static final int Get = 2; - public static final int Put = 4; - public static final int PutRef = 8; - public static final int fdexNameCaseSensitive = 1; - public static final int DISPID_UNKNOWN = -1; - public static final int DISPID_VALUE = 0; - public static final int DISPID_PROPERTYPUT = -3; - public static final int DISPID_NEWENUM = -4; - public static final int DISPID_EVALUATE = -5; - public static final int DISPID_CONSTRUCTOR = -6; - public static final int DISPID_DESTRUCTOR = -7; - public static final int DISPID_COLLECT = -8; - public static final int DISPID_AUTOSIZE = -500; - public static final int DISPID_BACKCOLOR = -501; - public static final int DISPID_BACKSTYLE = -502; - public static final int DISPID_BORDERCOLOR = -503; - public static final int DISPID_BORDERSTYLE = -504; - public static final int DISPID_BORDERWIDTH = -505; - public static final int DISPID_DRAWMODE = -507; - public static final int DISPID_DRAWSTYLE = -508; - public static final int DISPID_DRAWWIDTH = -509; - public static final int DISPID_FILLCOLOR = -510; - public static final int DISPID_FILLSTYLE = -511; - public static final int DISPID_FONT = -512; - public static final int DISPID_FORECOLOR = -513; - public static final int DISPID_ENABLED = -514; - public static final int DISPID_HWND = -515; - public static final int DISPID_TABSTOP = -516; - public static final int DISPID_TEXT = -517; - public static final int DISPID_CAPTION = -518; - public static final int DISPID_BORDERVISIBLE = -519; - public static final int DISPID_APPEARANCE = -520; - public static final int DISPID_MOUSEPOINTER = -521; - public static final int DISPID_MOUSEICON = -522; - public static final int DISPID_PICTURE = -523; - public static final int DISPID_VALID = -524; - public static final int DISPID_READYSTATE = -525; - public static final int DISPID_REFRESH = -550; - public static final int DISPID_DOCLICK = -551; - public static final int DISPID_ABOUTBOX = -552; - public static final int DISPID_CLICK = -600; - public static final int DISPID_DBLCLICK = -601; - public static final int DISPID_KEYDOWN = -602; - public static final int DISPID_KEYPRESS = -603; - public static final int DISPID_KEYUP = -604; - public static final int DISPID_MOUSEDOWN = -605; - public static final int DISPID_MOUSEMOVE = -606; - public static final int DISPID_MOUSEUP = -607; - public static final int DISPID_ERROREVENT = -608; - public static final int DISPID_READYSTATECHANGE = -609; - public static final int DISPID_AMBIENT_BACKCOLOR = -701; - public static final int DISPID_AMBIENT_DISPLAYNAME = -702; - public static final int DISPID_AMBIENT_FONT = -703; - public static final int DISPID_AMBIENT_FORECOLOR = -704; - public static final int DISPID_AMBIENT_LOCALEID = -705; - public static final int DISPID_AMBIENT_MESSAGEREFLECT = -706; - public static final int DISPID_AMBIENT_SCALEUNITS = -707; - public static final int DISPID_AMBIENT_TEXTALIGN = -708; - public static final int DISPID_AMBIENT_USERMODE = -709; - public static final int DISPID_AMBIENT_UIDEAD = -710; - public static final int DISPID_AMBIENT_SHOWGRABHANDLES = -711; - public static final int DISPID_AMBIENT_SHOWHATCHING = -712; - public static final int DISPID_AMBIENT_DISPLAYASDEFAULT = -713; - public static final int DISPID_AMBIENT_SUPPORTSMNEMONICS = -714; - public static final int DISPID_AMBIENT_AUTOCLIP = -715; - public static final int DISPID_AMBIENT_APPEARANCE = -716; - public static final int DISPID_AMBIENT_CODEPAGE = -725; - public static final int DISPID_AMBIENT_PALETTE = -726; - public static final int DISPID_AMBIENT_CHARSET = -727; - public static final int DISPID_AMBIENT_TRANSFERPRIORITY = -728; - /** - * This is public because Dispatch.cpp knows its name and accesses - * it directly to get the disptach id. You really can't rename - * it or make it private - */ - public int m_pDispatch; - +public class Dispatch extends JacobObject { + + /** + * Used to set the locale in a call. The user locale is another option + */ + public static final int LOCALE_SYSTEM_DEFAULT = 2048; + /** used by callN() and callSubN() */ + public static final int Method = 1; + /** used by callN() and callSubN() */ + public static final int Get = 2; + /** used by put() */ + public static final int Put = 4; + /** not used, probably intended for putRef() */ + public static final int PutRef = 8; + /** + * One of legal values for GetDispId. Not used in this layer and probably + * not needed. + */ + public static final int fdexNameCaseSensitive = 1; + + /** + * This is public because Dispatch.cpp knows its name and accesses it + * directly to get the dispatch id. You really can't rename it or make it + * private + */ + public int m_pDispatch; + /** program Id passed in by ActiveX components in their constructor */ - private String programId = null; - - private static int NOT_ATTACHED = 0; - - /** - * Dummy empty array used one doesn't have to be created on every - * invocation - */ - private final static Object[] NO_OBJECT_ARGS = new Object[0]; - /** - * Dummy empty array used one doesn't have to be created on every - * invocation - */ - private final static Variant[] NO_VARIANT_ARGS = new Variant[0]; - /** - * Dummy empty array used one doesn't have to be created on every - * invocation - */ - private final static int[] NO_INT_ARGS = new int[0]; - - - /** - * zero argument constructor that sets the dispatch pointer to 0 - * This is the only way to create a Dispatch without a value in the pointer field. - */ - public Dispatch() { - m_pDispatch = NOT_ATTACHED; - } - - /** - * This constructor calls createInstance with progid. This is the - * constructor used by the ActiveXComponent or by programs that - * don't like the activeX interface but wish to create new connections - * to windows programs. - *

- * This constructor always creates a new windows/program object - * because it is based on the CoCreate() windows function. - *

- * @throws IllegalArgumentException if null is passed in as the program id - *

- * @param requestedProgramId - */ - public Dispatch(String requestedProgramId) { - programId = requestedProgramId; - if (programId != null && !"".equals(programId)){ - createInstanceNative(requestedProgramId); - } else { - throw new IllegalArgumentException( - "Dispatch(String) does not accept null or an empty string as a parameter"); - } - } - - /** - * native call createInstance only used by the constructor with the same parm - * type. This probably should be private. It is the wrapper for the - * Windows CoCreate() call - *

- * This ends up calling CoCreate down in the JNI layer - *

- * The behavior is different if a ":" character exists in the progId. In that - * case CoGetObject and CreateInstance (someone needs to describe this better) - * - * @param progid - */ - private native void createInstanceNative(String progid); - - /** - * native call getActiveInstance only used by the constructor with the same parm - * type. This probably should be private. It is the wrapper for the - * Windows GetActiveObject() call - *

- * This ends up calling GetActiveObject down in the JNI layer - *

- * This does not have the special behavior for program ids with ":" in them - * that createInstance has. - * - * @param progid - */ - private native void getActiveInstanceNative(String progid); - - /** - * Wrapper around the native method - * @param pProgramIdentifier name of the program you wish to connect to - */ - protected void getActiveInstance(String pProgramIdentifier){ - if (pProgramIdentifier == null || "".equals(pProgramIdentifier)){ - throw new IllegalArgumentException("program id is required"); - } - this.programId = pProgramIdentifier; - getActiveInstanceNative(pProgramIdentifier); - } - - /** - * native call coCreateInstance only used by the constructor with the same parm - * type. This probably should be private. It is the wrapper for the - * Windows CoCreate() call - *

- * This ends up calling CoCreate down in the JNI layer - *

- * This does not have the special behavior for program ids with ":" in them - * that createInstance has. - * - * @param progid - */ - private native void coCreateInstanceNative(String progid); - - /** - * Wrapper around the native method - * @param pProgramIdentifier - */ - protected void coCreateInstance(String pProgramIdentifier){ - if (pProgramIdentifier == null || "".equals(pProgramIdentifier)){ - throw new IllegalArgumentException("program id is required"); - } - this.programId = pProgramIdentifier; - coCreateInstanceNative(pProgramIdentifier); - } - - /** - * Return a different interface by IID string. - *

- * Once you have a Dispatch object, you can navigate to the other - * interfaces of a COM object by calling QueryInterafce. - * The argument is an IID string in the format: - * "{9BF24410-B2E0-11D4-A695-00104BFF3241}". You typically get - * this string from the idl file (it's called uuid in there). - * Any interface you try to use must be derived from IDispatch. T - * The atl example uses this. - *

- * The Dispatch instance resulting from this query is instanciated in the - * JNI code. - * - * @param iid - * @return Dispatch a disptach that matches ?? - */ - public native Dispatch QueryInterface(String iid); - - /** - * Constructor that only gets called from JNI - * QueryInterface calls JNI code that looks up the object - * for the key passed in. The JNI CODE then creates a new dispatch object - * using this constructor - * @param pDisp - */ - protected Dispatch(int pDisp) { - m_pDispatch = pDisp; - } - - /** - * Constructor to be used by subclass that want to swap themselves - * in for the default Dispatch class. Usually you will have a - * class like WordDocument that is a subclass of Dispatch and it - * will have a constructor public WordDocument(Dispatch). That - * constructor should just call this constructor as super(Dispatch) - * - * @param dispatchToBeDisplaced - */ - public Dispatch(Dispatch dispatchToBeDisplaced) { - //TAKE OVER THE IDispatch POINTER - this.m_pDispatch = dispatchToBeDisplaced.m_pDispatch; - //NULL OUT THE INPUT POINTER - dispatchToBeDisplaced.m_pDispatch = NOT_ATTACHED; - } - - /** - * returns the program id if an activeX component created this - * otherwise it returns null. This was added to aid in debugging - * @return the program id an activeX component was created against - */ - public String getProgramId(){ - return programId; - } - - /* - * (non-Javadoc) - * @see java.lang.Object#finalize() - */ - protected void finalize() { - safeRelease(); - } - - /* - * (non-Javadoc) - * @see com.jacob.com.JacobObject#safeRelease() - */ - public void safeRelease() - { - super.safeRelease(); - if (isAttached()){ - release(); - m_pDispatch = NOT_ATTACHED; - } else { - // looks like a double release - if (isDebugEnabled()){debug(this.getClass().getName()+":"+this.hashCode()+" double release");} - } - } - - /** - * - * @return true if there is an underlying windows dispatch object - */ - protected boolean isAttached(){ - if (m_pDispatch == NOT_ATTACHED){ - return false; - } else { - return true; - } - } - - /** - * @throws IllegalStateException if this dispatch isn't hooked up - * @throws IllegalArgumentException if null the dispatch under test is null - * @param theOneInQuestion dispatch being tested - */ - private static void throwIfUnattachedDispatch(Dispatch theOneInQuestion){ - if (theOneInQuestion == null) { - throw new IllegalArgumentException("Can't pass in null Dispatch object"); - } else if (theOneInQuestion.isAttached()){ - return; - } else { - throw new IllegalStateException("Dispatch not hooked to windows memory"); - } - } - - /** - * Map args based on msdn doc - * This method relies on the variant constructor except for arrays - * @param objectToBeMadeIntoVariant - * @return Variant that represents the object - */ - protected static Variant obj2variant(Object objectToBeMadeIntoVariant) { - if (objectToBeMadeIntoVariant == null) - return new Variant(); - if (objectToBeMadeIntoVariant instanceof Variant) - // if a variant was passed in then be a slacker and just return it - return (Variant) objectToBeMadeIntoVariant; - if ( objectToBeMadeIntoVariant instanceof Integer - || objectToBeMadeIntoVariant instanceof Short - || objectToBeMadeIntoVariant instanceof String - || objectToBeMadeIntoVariant instanceof Boolean - || objectToBeMadeIntoVariant instanceof Double - || objectToBeMadeIntoVariant instanceof Float - || objectToBeMadeIntoVariant instanceof SafeArray - || objectToBeMadeIntoVariant instanceof Date - || objectToBeMadeIntoVariant instanceof Dispatch) - return new Variant(objectToBeMadeIntoVariant); - - // automatically convert arrays using reflection - Class c1 = objectToBeMadeIntoVariant.getClass(); - SafeArray sa = null; - if (c1.isArray()) { - 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, obj2variant(Array.get(e1, j))); - } - } - } else { - sa = new SafeArray(Variant.VariantVariant, len1); - for (int i = 0; i < len1; i++) { - sa.setVariant(i, obj2variant(Array.get(objectToBeMadeIntoVariant, i))); - } - } - return new Variant(sa); - } - throw new ClassCastException("cannot convert to Variant"); - } - - /** - * converts an array of objects into an array of Variants by - * repeatedly calling obj2Variant(Object) - * @param arrayOfObjectsToBeConverted - * @return Variant[] - */ - protected static Variant[] obj2variant(Object[] arrayOfObjectsToBeConverted) { - Variant vArg[] = new Variant[arrayOfObjectsToBeConverted.length]; - for (int i = 0; i < arrayOfObjectsToBeConverted.length; i++) { - vArg[i] = obj2variant(arrayOfObjectsToBeConverted[i]); - } - return vArg; - } - - - /** - * now private so only this object can asccess - * was: call this to explicitly release the com object before gc - * - */ - private native void release(); - - /** - * not implemented yet - * @param dispatchTarget - * @param name - * @param val - * @throws com.jacob.com.NotImplementedException - */ - public static void put_Casesensitive(Dispatch dispatchTarget, String name, Object val) { - throw new NotImplementedException("not implemented yet"); - } - - /*============================================================ - * start of the invokev section - * =========================================================== - */ - // eliminate _Guid arg - /** - * @param dispatchTarget - * @param name - * @param dispID - * @param lcid - * @param wFlags - * @param vArg - * @param uArgErr - */ - public static void invokeSubv(Dispatch dispatchTarget, String name, int dispID, - int lcid, int wFlags, Variant[] vArg, int[] uArgErr) { - throwIfUnattachedDispatch(dispatchTarget); - invokev(dispatchTarget, name, dispID, lcid, wFlags, vArg, uArgErr); - } - - /** - * @param dispatchTarget - * @param name - * @param wFlags - * @param vArg - * @param uArgErr - */ - public static void invokeSubv(Dispatch dispatchTarget, String name, int wFlags, - Variant[] vArg, int[] uArgErr) { - throwIfUnattachedDispatch(dispatchTarget); - invokev(dispatchTarget, name, 0, Dispatch.LOCALE_SYSTEM_DEFAULT, wFlags, vArg, uArgErr); - } - - /** - * @param dispatchTarget - * @param dispID - * @param wFlags - * @param vArg - * @param uArgErr - */ - public static void invokeSubv(Dispatch dispatchTarget, int dispID, int wFlags, - Variant[] vArg, int[] uArgErr) { - throwIfUnattachedDispatch(dispatchTarget); - invokev(dispatchTarget, null, dispID, Dispatch.LOCALE_SYSTEM_DEFAULT, wFlags, vArg, - uArgErr); - } - - /** - * not implemented yet - * @param dispatchTarget - * @param name - * @param values - * @return never returns anything because - * @throws com.jacob.com.NotImplementedException - */ - public static Variant callN_CaseSensitive(Dispatch dispatchTarget, String name, - Object[] values) { - throw new NotImplementedException("not implemented yet"); - } - - /** - * @param dispatchTarget - * @param name - * @param args an array of argument objects - */ - public static void callSubN(Dispatch dispatchTarget, String name, Object[] args) { - throwIfUnattachedDispatch(dispatchTarget); - invokeSubv(dispatchTarget, name, Dispatch.Method | Dispatch.Get, obj2variant(args), - new int[args.length]); - } - - /** - * @param dispatchTarget - * @param dispID - * @param args an array of argument objects - */ - public static void callSubN(Dispatch dispatchTarget, int dispID, Object[] args) { - throwIfUnattachedDispatch(dispatchTarget); - invokeSubv(dispatchTarget, dispID, Dispatch.Method | Dispatch.Get, obj2variant(args), - new int[args.length]); - } - - /*============================================================ - * start of the getIdsOfNames section - * =========================================================== - */ - /** - * @param dispatchTarget - * @param name - * @return int id for the passed in name - */ - public static int getIDOfName(Dispatch dispatchTarget, String name) { - int ids[] = getIDsOfNames(dispatchTarget, Dispatch.LOCALE_SYSTEM_DEFAULT, - new String[] { name }); - return ids[0]; - } - - /** - * @param dispatchTarget - * @param lcid - * @param names - * @return int[] in id array for passed in names - */ - // eliminated _Guid argument - public static native int[] getIDsOfNames(Dispatch dispatchTarget, int lcid, - String[] names); - - /** - * @param dispatchTarget - * @param names - * @return int[] int id array for passed in names - */ - // eliminated _Guid argument - public static int[] getIDsOfNames(Dispatch dispatchTarget, String[] names) { - return getIDsOfNames(dispatchTarget, - Dispatch.LOCALE_SYSTEM_DEFAULT, names); - } - - /*============================================================ - * start of the invokev section - * =========================================================== - */ - /** - * @param dispatchTarget - * @param name - * @param args - * @return Variant returned by call - */ - public static Variant callN(Dispatch dispatchTarget, String name, Object[] args) { - throwIfUnattachedDispatch(dispatchTarget); - return invokev(dispatchTarget, name, - Dispatch.Method | Dispatch.Get, obj2variant(args), - new int[args.length]); - } - - /** - * @param dispatchTarget - * @param dispID - * @param args - * @return Variant returned by call - */ - public static Variant callN(Dispatch dispatchTarget, int dispID, Object[] args) { - throwIfUnattachedDispatch(dispatchTarget); - return invokev(dispatchTarget, dispID, - Dispatch.Method | Dispatch.Get, obj2variant(args), - new int[args.length]); - } - - /** - * @param dispatchTarget - * @param name - * @param dispID - * @param lcid - * @param wFlags - * @param oArg - * @param uArgErr - * @return Variuant returned by invoke - */ - public static Variant invoke(Dispatch dispatchTarget, String name, int dispID, - int lcid, int wFlags, Object[] oArg, int[] uArgErr) { - throwIfUnattachedDispatch(dispatchTarget); - return invokev(dispatchTarget, name, dispID, lcid, wFlags, obj2variant(oArg), - uArgErr); - } - - /** - * @param dispatchTarget - * @param name - * @param wFlags - * @param oArg - * @param uArgErr - * @return Variuant returned by invoke - */ - public static Variant invoke(Dispatch dispatchTarget, String name, int wFlags, - Object[] oArg, int[] uArgErr) { - throwIfUnattachedDispatch(dispatchTarget); - return invokev(dispatchTarget, name, wFlags, obj2variant(oArg), uArgErr); - } - - /** - * @param dispatchTarget - * @param dispID - * @param wFlags - * @param oArg - * @param uArgErr - * @return Variuant returned by invoke - */ - public static Variant invoke(Dispatch dispatchTarget, int dispID, int wFlags, - Object[] oArg, int[] uArgErr) { - throwIfUnattachedDispatch(dispatchTarget); - return invokev(dispatchTarget, dispID, wFlags, obj2variant(oArg), uArgErr); - } - - /*============================================================ - * start of the callN section - * =========================================================== - */ - - /** - * @param dispatchTarget - * @param name - * @return Variant retuned by underlying callN - */ - public static Variant call(Dispatch dispatchTarget, String name) { - throwIfUnattachedDispatch(dispatchTarget); - return callN(dispatchTarget, name, NO_VARIANT_ARGS); - } - - /** - * @param dispatchTarget - * @param name - * @param a1 - * @return Variant retuned by underlying callN - */ - public static Variant call(Dispatch dispatchTarget, String name, Object a1) { - throwIfUnattachedDispatch(dispatchTarget); - return callN(dispatchTarget, name, new Object[] { a1 }); - } - - /** - * @param dispatchTarget - * @param name - * @param a1 - * @param a2 - * @return Variant retuned by underlying callN - */ - public static Variant call(Dispatch dispatchTarget, String name, Object a1, Object a2) { - throwIfUnattachedDispatch(dispatchTarget); - return callN(dispatchTarget, name, new Object[] { a1, a2 }); - } - - /** - * @param dispatchTarget - * @param name - * @param a1 - * @param a2 - * @param a3 - * @return Variant retuned by underlying callN - */ - public static Variant call(Dispatch dispatchTarget, String name, Object a1, Object a2, - Object a3) { - throwIfUnattachedDispatch(dispatchTarget); - return callN(dispatchTarget, name, new Object[] { a1, a2, a3 }); - } - - /** - * @param dispatchTarget - * @param name - * @param a1 - * @param a2 - * @param a3 - * @param a4 - * @return Variant retuned by underlying callN - */ - public static Variant call(Dispatch dispatchTarget, String name, Object a1, Object a2, - Object a3, Object a4) { - throwIfUnattachedDispatch(dispatchTarget); - return callN(dispatchTarget, name, new Object[] { a1, a2, a3, a4 }); - } - - /** - * @param dispatchTarget - * @param name - * @param a1 - * @param a2 - * @param a3 - * @param a4 - * @param a5 - * @return Variant retuned by underlying callN - */ - public static Variant call(Dispatch dispatchTarget, String name, Object a1, Object a2, - Object a3, Object a4, Object a5) { - throwIfUnattachedDispatch(dispatchTarget); - return callN(dispatchTarget, name, new Object[] { a1, a2, a3, a4, a5 }); - } - - /** - * @param dispatchTarget - * @param name - * @param a1 - * @param a2 - * @param a3 - * @param a4 - * @param a5 - * @param a6 - * @return Variant retuned by underlying callN - */ - public static Variant call(Dispatch dispatchTarget, String name, Object a1, Object a2, - Object a3, Object a4, Object a5, Object a6) { - throwIfUnattachedDispatch(dispatchTarget); - return callN(dispatchTarget, name, new Object[] { a1, a2, a3, a4, a5, a6 }); - } - - /** - * @param dispatchTarget - * @param name - * @param a1 - * @param a2 - * @param a3 - * @param a4 - * @param a5 - * @param a6 - * @param a7 - * @return Variant retuned by underlying callN - */ - public static Variant call(Dispatch dispatchTarget, String name, Object a1, Object a2, - Object a3, Object a4, Object a5, Object a6, Object a7) { - throwIfUnattachedDispatch(dispatchTarget); - return callN(dispatchTarget, name, new Object[] { a1, a2, a3, a4, a5, a6, a7 }); - } - - /** - * @param dispatchTarget - * @param name - * @param a1 - * @param a2 - * @param a3 - * @param a4 - * @param a5 - * @param a6 - * @param a7 - * @param a8 - * @return Variant retuned by underlying callN - */ - public static Variant call(Dispatch dispatchTarget, String name, Object a1, Object a2, - Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { - throwIfUnattachedDispatch(dispatchTarget); - return callN(dispatchTarget, name, - new Object[] { a1, a2, a3, a4, a5, a6, a7, a8 }); - } - - /** - * @param dispatchTarget - * @param dispid - * @return Variant retuned by underlying callN - */ - public static Variant call(Dispatch dispatchTarget, int dispid) { - throwIfUnattachedDispatch(dispatchTarget); - return callN(dispatchTarget, dispid, NO_VARIANT_ARGS); - } - - /** - * @param dispatchTarget - * @param dispid - * @param a1 - * @return Variant retuned by underlying callN - */ - public static Variant call(Dispatch dispatchTarget, int dispid, Object a1) { - throwIfUnattachedDispatch(dispatchTarget); - return callN(dispatchTarget, dispid, new Object[] { a1 }); - } - - /** - * @param dispatchTarget - * @param dispid - * @param a1 - * @param a2 - * @return Variant retuned by underlying callN - */ - public static Variant call(Dispatch dispatchTarget, int dispid, Object a1, Object a2) { - throwIfUnattachedDispatch(dispatchTarget); - return callN(dispatchTarget, dispid, new Object[] { a1, a2 }); - } - - /** - * @param dispatchTarget - * @param dispid - * @param a1 - * @param a2 - * @param a3 - * @return Variant retuned by underlying callN - */ - public static Variant call(Dispatch dispatchTarget, int dispid, Object a1, Object a2, - Object a3) { - throwIfUnattachedDispatch(dispatchTarget); - return callN(dispatchTarget, dispid, new Object[] { a1, a2, a3 }); - } - - /** - * @param dispatchTarget - * @param dispid - * @param a1 - * @param a2 - * @param a3 - * @param a4 - * @return Variant retuned by underlying callN - */ - public static Variant call(Dispatch dispatchTarget, int dispid, Object a1, Object a2, - Object a3, Object a4) { - throwIfUnattachedDispatch(dispatchTarget); - return callN(dispatchTarget, dispid, new Object[] { a1, a2, a3, a4 }); - } - - /** - * @param dispatchTarget - * @param dispid - * @param a1 - * @param a2 - * @param a3 - * @param a4 - * @param a5 - * @return Variant retuned by underlying callN - */ - public static Variant call(Dispatch dispatchTarget, int dispid, Object a1, Object a2, - Object a3, Object a4, Object a5) { - throwIfUnattachedDispatch(dispatchTarget); - return callN(dispatchTarget, dispid, new Object[] { a1, a2, a3, a4, a5 }); - } - - /** - * @param dispatchTarget - * @param dispid - * @param a1 - * @param a2 - * @param a3 - * @param a4 - * @param a5 - * @param a6 - * @return Variant retuned by underlying callN - */ - public static Variant call(Dispatch dispatchTarget, int dispid, Object a1, Object a2, - Object a3, Object a4, Object a5, Object a6) { - throwIfUnattachedDispatch(dispatchTarget); - return callN(dispatchTarget, dispid, new Object[] { a1, a2, a3, a4, a5, a6 }); - } - - /** - * @param dispatchTarget - * @param dispid - * @param a1 - * @param a2 - * @param a3 - * @param a4 - * @param a5 - * @param a6 - * @param a7 - * @return Variant retuned by underlying callN - */ - public static Variant call(Dispatch dispatchTarget, int dispid, Object a1, Object a2, - Object a3, Object a4, Object a5, Object a6, Object a7) { - throwIfUnattachedDispatch(dispatchTarget); - return callN(dispatchTarget, dispid, new Object[] { a1, a2, a3, a4, a5, a6, a7 }); - } - - /** - * @param dispatchTarget - * @param dispid - * @param a1 - * @param a2 - * @param a3 - * @param a4 - * @param a5 - * @param a6 - * @param a7 - * @param a8 - * @return Variant retuned by underlying callN - */ - public static Variant call(Dispatch dispatchTarget, int dispid, Object a1, Object a2, - Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { - throwIfUnattachedDispatch(dispatchTarget); - return callN(dispatchTarget, dispid, new Object[] { a1, a2, a3, a4, a5, a6, a7, - a8 }); - } - - /*============================================================ - * start of the invoke section - * =========================================================== - */ - /** - * @param dispatchTarget - * @param name - * @param val - */ - public static void put(Dispatch dispatchTarget, String name, Object val) { - throwIfUnattachedDispatch(dispatchTarget); - invoke(dispatchTarget, name, Dispatch.Put, new Object[] { val }, new int[1]); - } - - /** - * @param dispatchTarget - * @param dispid - * @param val - */ - public static void put(Dispatch dispatchTarget, int dispid, Object val) { - throwIfUnattachedDispatch(dispatchTarget); - invoke(dispatchTarget, dispid, Dispatch.Put, new Object[] { val }, new int[1]); - } - - /*============================================================ - * start of the invokev section - * =========================================================== - */ - // removed _Guid argument - /** - * @param dispatchTarget - * @param name - * @param dispID - * @param lcid - * @param wFlags - * @param vArg - * @param uArgErr - * @return Variant returned by underlying invokev - */ - public static native Variant invokev(Dispatch dispatchTarget, String name, int dispID, - int lcid, int wFlags, Variant[] vArg, int[] uArgErr); - - /** - * @param dispatchTarget - * @param name - * @param wFlags - * @param vArg - * @param uArgErr - * @return Variant returned by underlying invokev - */ - public static Variant invokev(Dispatch dispatchTarget, String name, int wFlags, - Variant[] vArg, int[] uArgErr) { - throwIfUnattachedDispatch(dispatchTarget); - return invokev(dispatchTarget, name, 0, Dispatch.LOCALE_SYSTEM_DEFAULT, wFlags, vArg, - uArgErr); - } - - /** - * @param dispatchTarget - * @param name - * @param wFlags - * @param vArg - * @param uArgErr - * @param wFlagsEx - * @return Variant returned by underlying invokev - */ - public static Variant invokev(Dispatch dispatchTarget, String name, int wFlags, - Variant[] vArg, int[] uArgErr, int wFlagsEx) { - throwIfUnattachedDispatch(dispatchTarget); - // do not implement IDispatchEx for now - return invokev(dispatchTarget, name, 0, Dispatch.LOCALE_SYSTEM_DEFAULT, wFlags, vArg, - uArgErr); - } - - /** - * @param dispatchTarget - * @param dispID - * @param wFlags - * @param vArg - * @param uArgErr - * @return Variant returned by underlying invokev - */ - public static Variant invokev(Dispatch dispatchTarget, int dispID, int wFlags, - Variant[] vArg, int[] uArgErr) { - throwIfUnattachedDispatch(dispatchTarget); - return invokev(dispatchTarget, null, dispID, - Dispatch.LOCALE_SYSTEM_DEFAULT, wFlags, vArg, - uArgErr); - } - - /*============================================================ - * start of the invokeSubv section - * =========================================================== - */ - - // removed _Guid argument - /** - * @param dispatchTarget - * @param name - * @param dispid - * @param lcid - * @param wFlags - * @param oArg - * @param uArgErr - */ - public static void invokeSub(Dispatch dispatchTarget, String name, int dispid, - int lcid, int wFlags, Object[] oArg, int[] uArgErr) { - throwIfUnattachedDispatch(dispatchTarget); - invokeSubv(dispatchTarget, name, dispid, lcid, wFlags, obj2variant(oArg), uArgErr); - } - - /*============================================================ - * start of the invokeSub section - * =========================================================== - */ - /** - * @param dispatchTarget - * @param name - * @param wFlags - * @param oArg - * @param uArgErr - */ - public static void invokeSub(Dispatch dispatchTarget, String name, int wFlags, - Object[] oArg, int[] uArgErr) { - throwIfUnattachedDispatch(dispatchTarget); - invokeSub(dispatchTarget, name, 0, Dispatch.LOCALE_SYSTEM_DEFAULT, wFlags, oArg, uArgErr); - } - - /** - * @param dispatchTarget - * @param dispid - * @param wFlags - * @param oArg - * @param uArgErr - */ - public static void invokeSub(Dispatch dispatchTarget, int dispid, int wFlags, - Object[] oArg, int[] uArgErr) { - throwIfUnattachedDispatch(dispatchTarget); - invokeSub(dispatchTarget, null, dispid, Dispatch.LOCALE_SYSTEM_DEFAULT, wFlags, oArg, - uArgErr); - } - - /*============================================================ - * start of the callSubN section - * =========================================================== - */ - /** - * makes call to native callSubN - * @param dispatchTarget - * @param name - */ - public static void callSub(Dispatch dispatchTarget, String name) { - throwIfUnattachedDispatch(dispatchTarget); - callSubN(dispatchTarget, name, NO_OBJECT_ARGS); - } - - /** - * makes call to native callSubN - * @param dispatchTarget - * @param name - * @param a1 - */ - public static void callSub(Dispatch dispatchTarget, String name, Object a1) { - throwIfUnattachedDispatch(dispatchTarget); - callSubN(dispatchTarget, name, new Object[] { a1 }); - } - - /** - * makes call to native callSubN - * @param dispatchTarget - * @param name - * @param a1 - * @param a2 - */ - public static void callSub(Dispatch dispatchTarget, String name, Object a1, Object a2) { - throwIfUnattachedDispatch(dispatchTarget); - callSubN(dispatchTarget, name, new Object[] { a1, a2 }); - } - - /** - * makes call to native callSubN - * @param dispatchTarget - * @param name - * @param a1 - * @param a2 - * @param a3 - */ - public static void callSub(Dispatch dispatchTarget, String name, Object a1, Object a2, - Object a3) { - throwIfUnattachedDispatch(dispatchTarget); - callSubN(dispatchTarget, name, new Object[] { a1, a2, a3 }); - } - - /** - * makes call to native callSubN - * @param dispatchTarget - * @param name - * @param a1 - * @param a2 - * @param a3 - * @param a4 - */ - public static void callSub(Dispatch dispatchTarget, String name, Object a1, Object a2, - Object a3, Object a4) { - throwIfUnattachedDispatch(dispatchTarget); - callSubN(dispatchTarget, name, new Object[] { a1, a2, a3, a4 }); - } - - /** - * makes call to native callSubN - * @param dispatchTarget - * @param name - * @param a1 - * @param a2 - * @param a3 - * @param a4 - * @param a5 - */ - public static void callSub(Dispatch dispatchTarget, String name, Object a1, Object a2, - Object a3, Object a4, Object a5) { - throwIfUnattachedDispatch(dispatchTarget); - callSubN(dispatchTarget, name, new Object[] { a1, a2, a3, a4, a5 }); - } - - /** - * makes call to native callSubN - * @param dispatchTarget - * @param name - * @param a1 - * @param a2 - * @param a3 - * @param a4 - * @param a5 - * @param a6 - */ - public static void callSub(Dispatch dispatchTarget, String name, Object a1, Object a2, - Object a3, Object a4, Object a5, Object a6) { - throwIfUnattachedDispatch(dispatchTarget); - callSubN(dispatchTarget, name, new Object[] { a1, a2, a3, a4, a5, a6 }); - } - - /** - * makes call to native callSubN - * @param dispatchTarget - * @param name - * @param a1 - * @param a2 - * @param a3 - * @param a4 - * @param a5 - * @param a6 - * @param a7 - */ - public static void callSub(Dispatch dispatchTarget, String name, Object a1, Object a2, - Object a3, Object a4, Object a5, Object a6, Object a7) { - throwIfUnattachedDispatch(dispatchTarget); - callSubN(dispatchTarget, name, new Object[] { a1, a2, a3, a4, a5, a6, a7 }); - } - - /** - * makes call to native callSubN - * @param dispatchTarget - * @param name - * @param a1 - * @param a2 - * @param a3 - * @param a4 - * @param a5 - * @param a6 - * @param a7 - * @param a8 - */ - public static void callSub(Dispatch dispatchTarget, String name, Object a1, Object a2, - Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { - throwIfUnattachedDispatch(dispatchTarget); - callSubN(dispatchTarget, name, new Object[] { a1, a2, a3, a4, a5, a6, a7, a8 }); - } - - /** - * makes call to native callSubN - * @param dispatchTarget - * @param dispid - */ - public static void callSub(Dispatch dispatchTarget, int dispid) { - throwIfUnattachedDispatch(dispatchTarget); - callSubN(dispatchTarget, dispid, NO_OBJECT_ARGS); - } - - /** - * makes call to native callSubN - * @param dispatchTarget - * @param dispid - * @param a1 - */ - public static void callSub(Dispatch dispatchTarget, int dispid, Object a1) { - throwIfUnattachedDispatch(dispatchTarget); - callSubN(dispatchTarget, dispid, new Object[] { a1 }); - } - - /** - * makes call to native callSubN - * @param dispatchTarget - * @param dispid - * @param a1 - * @param a2 - */ - public static void callSub(Dispatch dispatchTarget, int dispid, Object a1, Object a2) { - throwIfUnattachedDispatch(dispatchTarget); - callSubN(dispatchTarget, dispid, new Object[] { a1, a2 }); - } - - /** - * makes call to native callSubN - * @param dispatchTarget - * @param dispid - * @param a1 - * @param a2 - * @param a3 - */ - public static void callSub(Dispatch dispatchTarget, int dispid, Object a1, Object a2, - Object a3) { - callSubN(dispatchTarget, dispid, new Object[] { a1, a2, a3 }); - } - - /** - * makes call to native callSubN - * @param dispatchTarget - * @param dispid - * @param a1 - * @param a2 - * @param a3 - * @param a4 - */ - public static void callSub(Dispatch dispatchTarget, int dispid, Object a1, Object a2, - Object a3, Object a4) { - throwIfUnattachedDispatch(dispatchTarget); - callSubN(dispatchTarget, dispid, new Object[] { a1, a2, a3, a4 }); - } - - /** - * makes call to native callSubN - * @param dispatchTarget - * @param dispid - * @param a1 - * @param a2 - * @param a3 - * @param a4 - * @param a5 - */ - public static void callSub(Dispatch dispatchTarget, int dispid, Object a1, Object a2, - Object a3, Object a4, Object a5) { - throwIfUnattachedDispatch(dispatchTarget); - callSubN(dispatchTarget, dispid, new Object[] { a1, a2, a3, a4, a5 }); - } - - /** - * makes call to native callSubN - * @param dispatchTarget - * @param dispid - * @param a1 - * @param a2 - * @param a3 - * @param a4 - * @param a5 - * @param a6 - */ - public static void callSub(Dispatch dispatchTarget, int dispid, Object a1, Object a2, - Object a3, Object a4, Object a5, Object a6) { - throwIfUnattachedDispatch(dispatchTarget); - callSubN(dispatchTarget, dispid, new Object[] { a1, a2, a3, a4, a5, a6 }); - } - - /** - * makes call to native callSubN - * @param dispatchTarget - * @param dispid - * @param a1 - * @param a2 - * @param a3 - * @param a4 - * @param a5 - * @param a6 - * @param a7 - */ - public static void callSub(Dispatch dispatchTarget, int dispid, Object a1, Object a2, - Object a3, Object a4, Object a5, Object a6, Object a7) { - throwIfUnattachedDispatch(dispatchTarget); - callSubN(dispatchTarget, dispid, new Object[] { a1, a2, a3, a4, a5, a6, a7 }); - } - - /** - * makes call to native callSubN - * @param dispatchTarget - * @param dispid - * @param a1 - * @param a2 - * @param a3 - * @param a4 - * @param a5 - * @param a6 - * @param a7 - * @param a8 - */ - public static void callSub(Dispatch dispatchTarget, int dispid, Object a1, Object a2, - Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { - callSubN(dispatchTarget, dispid, new Object[] { a1, a2, a3, a4, a5, a6, a7, a8 }); - } - - /*============================================================ - * start of the invokev section - * =========================================================== - */ - /** - * Cover for call to underlying invokev() - * @param dispatchTarget - * @param name - * @return Variant returned by the request for retrieval of parameter - */ - public static Variant get(Dispatch dispatchTarget, String name) { - throwIfUnattachedDispatch(dispatchTarget); - return invokev(dispatchTarget, name, Dispatch.Get, NO_VARIANT_ARGS, NO_INT_ARGS); - } - - /** - * Cover for call to underlying invokev() - * @param dispatchTarget - * @param dispid - * @return Variant returned by the request for retrieval of parameter - */ - public static Variant get(Dispatch dispatchTarget, int dispid) { - throwIfUnattachedDispatch(dispatchTarget); - return invokev(dispatchTarget, dispid, Dispatch.Get, NO_VARIANT_ARGS, NO_INT_ARGS); - } - - /*============================================================ - * start of the invoke section - * =========================================================== - */ - /** - * cover for underlying call to invoke - * @param dispatchTarget - * @param name - * @param val - */ - public static void putRef(Dispatch dispatchTarget, String name, Object val) { - throwIfUnattachedDispatch(dispatchTarget); - invoke(dispatchTarget, name, Dispatch.PutRef, new Object[] { val }, new int[1]); - } - - /** - * cover for underlying call to invoke - * @param dispatchTarget - * @param dispid - * @param val - */ - public static void putRef(Dispatch dispatchTarget, int dispid, Object val) { - throwIfUnattachedDispatch(dispatchTarget); - invoke(dispatchTarget, dispid, Dispatch.PutRef, new Object[] { val }, new int[1]); - } - - /** - * not implemented yet - * @param dispatchTarget - * @param name - * @return Variant never returned - * @throws com.jacob.com.NotImplementedException - */ - public static Variant get_CaseSensitive(Dispatch dispatchTarget, String name) { - throw new NotImplementedException("not implemented yet"); - } - + private String programId = null; + + private static int NOT_ATTACHED = 0; + + /** + * Dummy empty array used one doesn't have to be created on every invocation + */ + private final static Object[] NO_OBJECT_ARGS = new Object[0]; + /** + * Dummy empty array used one doesn't have to be created on every invocation + */ + private final static Variant[] NO_VARIANT_ARGS = new Variant[0]; + /** + * Dummy empty array used one doesn't have to be created on every invocation + */ + private final static int[] NO_INT_ARGS = new int[0]; + + /** + * zero argument constructor that sets the dispatch pointer to 0 This is the + * only way to create a Dispatch without a value in the pointer field. + */ + public Dispatch() { + m_pDispatch = NOT_ATTACHED; + } + + /** + * This constructor calls createInstance with progid. This is the + * constructor used by the ActiveXComponent or by programs that don't like + * the activeX interface but wish to create new connections to windows + * programs. + *

+ * This constructor always creates a new windows/program object because it + * is based on the CoCreate() windows function. + *

+ * + * @param requestedProgramId + * @throws IllegalArgumentException + * if null is passed in as the program id + *

+ */ + public Dispatch(String requestedProgramId) { + programId = requestedProgramId; + if (programId != null && !"".equals(programId)) { + createInstanceNative(requestedProgramId); + } else { + throw new IllegalArgumentException( + "Dispatch(String) does not accept null or an empty string as a parameter"); + } + } + + /** + * native call createInstance only used by the constructor with the same + * parm type. This probably should be private. It is the wrapper for the + * Windows CoCreate() call + *

+ * This ends up calling CoCreate down in the JNI layer + *

+ * The behavior is different if a ":" character exists in the progId. In + * that case CoGetObject and CreateInstance (someone needs to describe this + * better) + * + * @param progid + */ + private native void createInstanceNative(String progid); + + /** + * native call getActiveInstance only used by the constructor with the same + * parm type. This probably should be private. It is the wrapper for the + * Windows GetActiveObject() call + *

+ * This ends up calling GetActiveObject down in the JNI layer + *

+ * This does not have the special behavior for program ids with ":" in them + * that createInstance has. + * + * @param progid + */ + private native void getActiveInstanceNative(String progid); + + /** + * Wrapper around the native method + * + * @param pProgramIdentifier + * name of the program you wish to connect to + */ + protected void getActiveInstance(String pProgramIdentifier) { + if (pProgramIdentifier == null || "".equals(pProgramIdentifier)) { + throw new IllegalArgumentException("program id is required"); + } + this.programId = pProgramIdentifier; + getActiveInstanceNative(pProgramIdentifier); + } + + /** + * native call coCreateInstance only used by the constructor with the same + * parm type. This probably should be private. It is the wrapper for the + * Windows CoCreate() call + *

+ * This ends up calling CoCreate down in the JNI layer + *

+ * This does not have the special behavior for program ids with ":" in them + * that createInstance has. + * + * @param progid + */ + private native void coCreateInstanceNative(String progid); + + /** + * Wrapper around the native method + * + * @param pProgramIdentifier + */ + protected void coCreateInstance(String pProgramIdentifier) { + if (pProgramIdentifier == null || "".equals(pProgramIdentifier)) { + throw new IllegalArgumentException("program id is required"); + } + this.programId = pProgramIdentifier; + coCreateInstanceNative(pProgramIdentifier); + } + + /** + * Return a different interface by IID string. + *

+ * Once you have a Dispatch object, you can navigate to the other interfaces + * of a COM object by calling QueryInterafce. The argument is an IID string + * in the format: "{9BF24410-B2E0-11D4-A695-00104BFF3241}". You typically + * get this string from the idl file (it's called uuid in there). Any + * interface you try to use must be derived from IDispatch. T The atl + * example uses this. + *

+ * The Dispatch instance resulting from this query is instanciated in the + * JNI code. + * + * @param iid + * @return Dispatch a disptach that matches ?? + */ + public native Dispatch QueryInterface(String iid); + + /** + * Constructor that only gets called from JNI QueryInterface calls JNI code + * that looks up the object for the key passed in. The JNI CODE then creates + * a new dispatch object using this constructor + * + * @param pDisp + */ + protected Dispatch(int pDisp) { + m_pDispatch = pDisp; + } + + /** + * Constructor to be used by subclass that want to swap themselves in for + * the default Dispatch class. Usually you will have a class like + * WordDocument that is a subclass of Dispatch and it will have a + * constructor public WordDocument(Dispatch). That constructor should just + * call this constructor as super(Dispatch) + * + * @param dispatchToBeDisplaced + */ + public Dispatch(Dispatch dispatchToBeDisplaced) { + // TAKE OVER THE IDispatch POINTER + this.m_pDispatch = dispatchToBeDisplaced.m_pDispatch; + // NULL OUT THE INPUT POINTER + dispatchToBeDisplaced.m_pDispatch = NOT_ATTACHED; + } + + /** + * returns the program id if an activeX component created this otherwise it + * returns null. This was added to aid in debugging + * + * @return the program id an activeX component was created against + */ + public String getProgramId() { + return programId; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#finalize() + */ + protected void finalize() { + safeRelease(); + } + + /* + * (non-Javadoc) + * + * @see com.jacob.com.JacobObject#safeRelease() + */ + public void safeRelease() { + super.safeRelease(); + if (isAttached()) { + release(); + m_pDispatch = NOT_ATTACHED; + } else { + // looks like a double release + if (isDebugEnabled()) { + debug(this.getClass().getName() + ":" + this.hashCode() + + " double release"); + } + } + } + + /** + * + * @return true if there is an underlying windows dispatch object + */ + protected boolean isAttached() { + if (m_pDispatch == NOT_ATTACHED) { + return false; + } else { + return true; + } + } + + /** + * @param theOneInQuestion + * dispatch being tested + * @throws IllegalStateException + * if this dispatch isn't hooked up + * @throws IllegalArgumentException + * if null the dispatch under test is null + */ + private static void throwIfUnattachedDispatch(Dispatch theOneInQuestion) { + if (theOneInQuestion == null) { + throw new IllegalArgumentException( + "Can't pass in null Dispatch object"); + } else if (theOneInQuestion.isAttached()) { + return; + } else { + throw new IllegalStateException( + "Dispatch not hooked to windows memory"); + } + } + + /** + * now private so only this object can access was: call this to explicitly + * release the com object before gc + * + */ + private native void release(); + + /** + * not implemented yet + * + * @param dispatchTarget + * @param name + * @param val + * @throws com.jacob.com.NotImplementedException + */ + public static void put_Casesensitive(Dispatch dispatchTarget, String name, + Object val) { + throw new NotImplementedException("not implemented yet"); + } + + /* + * ============================================================ start of the + * invokev section + * =========================================================== + */ + // eliminate _Guid arg + /** + * @param dispatchTarget + * @param name + * @param dispID + * @param lcid + * @param wFlags + * @param vArg + * @param uArgErr + */ + public static void invokeSubv(Dispatch dispatchTarget, String name, + int dispID, int lcid, int wFlags, Variant[] vArg, int[] uArgErr) { + throwIfUnattachedDispatch(dispatchTarget); + invokev(dispatchTarget, name, dispID, lcid, wFlags, vArg, uArgErr); + } + + /** + * @param dispatchTarget + * @param name + * @param wFlags + * @param vArg + * @param uArgErr + */ + public static void invokeSubv(Dispatch dispatchTarget, String name, + int wFlags, Variant[] vArg, int[] uArgErr) { + throwIfUnattachedDispatch(dispatchTarget); + invokev(dispatchTarget, name, 0, Dispatch.LOCALE_SYSTEM_DEFAULT, + wFlags, vArg, uArgErr); + } + + /** + * @param dispatchTarget + * @param dispID + * @param wFlags + * @param vArg + * @param uArgErr + */ + public static void invokeSubv(Dispatch dispatchTarget, int dispID, + int wFlags, Variant[] vArg, int[] uArgErr) { + throwIfUnattachedDispatch(dispatchTarget); + invokev(dispatchTarget, null, dispID, Dispatch.LOCALE_SYSTEM_DEFAULT, + wFlags, vArg, uArgErr); + } + + /** + * not implemented yet + * + * @param dispatchTarget + * @param name + * @param values + * @return never returns anything because + * @throws com.jacob.com.NotImplementedException + */ + public static Variant callN_CaseSensitive(Dispatch dispatchTarget, + String name, Object[] values) { + throw new NotImplementedException("not implemented yet"); + } + + /** + * @param dispatchTarget + * @param name + * @param args + * an array of argument objects + */ + public static void callSubN(Dispatch dispatchTarget, String name, + Object[] args) { + throwIfUnattachedDispatch(dispatchTarget); + invokeSubv(dispatchTarget, name, Dispatch.Method | Dispatch.Get, + VariantUtilities.objectsToVariants(args), + new int[args.length]); + } + + /** + * @param dispatchTarget + * @param dispID + * @param args + * an array of argument objects + */ + public static void callSubN(Dispatch dispatchTarget, int dispID, + Object[] args) { + throwIfUnattachedDispatch(dispatchTarget); + invokeSubv(dispatchTarget, dispID, Dispatch.Method | Dispatch.Get, + VariantUtilities.objectsToVariants(args), + new int[args.length]); + } + + /* + * ============================================================ start of the + * getIdsOfNames section + * =========================================================== + */ + /** + * @param dispatchTarget + * @param name + * @return int id for the passed in name + */ + public static int getIDOfName(Dispatch dispatchTarget, String name) { + int ids[] = getIDsOfNames(dispatchTarget, + Dispatch.LOCALE_SYSTEM_DEFAULT, new String[] { name }); + return ids[0]; + } + + /** + * @param dispatchTarget + * @param lcid + * @param names + * @return int[] in id array for passed in names + */ + // eliminated _Guid argument + public static native int[] getIDsOfNames(Dispatch dispatchTarget, int lcid, + String[] names); + + /** + * @param dispatchTarget + * @param names + * @return int[] int id array for passed in names + */ + // eliminated _Guid argument + public static int[] getIDsOfNames(Dispatch dispatchTarget, String[] names) { + return getIDsOfNames(dispatchTarget, Dispatch.LOCALE_SYSTEM_DEFAULT, + names); + } + + /* + * ============================================================ start of the + * invokev section + * =========================================================== + */ + /** + * @param dispatchTarget + * @param name + * @param args + * @return Variant returned by call + */ + public static Variant callN(Dispatch dispatchTarget, String name, + Object[] args) { + throwIfUnattachedDispatch(dispatchTarget); + return invokev(dispatchTarget, name, Dispatch.Method | Dispatch.Get, + VariantUtilities.objectsToVariants(args), + new int[args.length]); + } + + /** + * @param dispatchTarget + * @param dispID + * @param args + * @return Variant returned by call + */ + public static Variant callN(Dispatch dispatchTarget, int dispID, + Object[] args) { + throwIfUnattachedDispatch(dispatchTarget); + return invokev(dispatchTarget, dispID, Dispatch.Method | Dispatch.Get, + VariantUtilities.objectsToVariants(args), + new int[args.length]); + } + + /** + * @param dispatchTarget + * @param name + * @param dispID + * @param lcid + * @param wFlags + * @param oArg + * @param uArgErr + * @return Variant returned by invoke + */ + public static Variant invoke(Dispatch dispatchTarget, String name, + int dispID, int lcid, int wFlags, Object[] oArg, int[] uArgErr) { + throwIfUnattachedDispatch(dispatchTarget); + return invokev(dispatchTarget, name, dispID, lcid, wFlags, + VariantUtilities.objectsToVariants(oArg), uArgErr); + } + + /** + * @param dispatchTarget + * @param name + * @param wFlags + * @param oArg + * @param uArgErr + * @return Variant returned by invoke + */ + public static Variant invoke(Dispatch dispatchTarget, String name, + int wFlags, Object[] oArg, int[] uArgErr) { + throwIfUnattachedDispatch(dispatchTarget); + return invokev(dispatchTarget, name, wFlags, VariantUtilities + .objectsToVariants(oArg), uArgErr); + } + + /** + * @param dispatchTarget + * @param dispID + * @param wFlags + * @param oArg + * @param uArgErr + * @return Variant returned by invoke + */ + public static Variant invoke(Dispatch dispatchTarget, int dispID, + int wFlags, Object[] oArg, int[] uArgErr) { + throwIfUnattachedDispatch(dispatchTarget); + return invokev(dispatchTarget, dispID, wFlags, VariantUtilities + .objectsToVariants(oArg), uArgErr); + } + + /* + * ============================================================ start of the + * callN section =========================================================== + */ + + /** + * @param dispatchTarget + * @param name + * @return Variant returned by underlying callN + */ + public static Variant call(Dispatch dispatchTarget, String name) { + throwIfUnattachedDispatch(dispatchTarget); + return callN(dispatchTarget, name, NO_VARIANT_ARGS); + } + + /** + * @param dispatchTarget + * @param name + * @param a1 + * @return Variant returned by underlying callN + */ + public static Variant call(Dispatch dispatchTarget, String name, Object a1) { + throwIfUnattachedDispatch(dispatchTarget); + return callN(dispatchTarget, name, new Object[] { a1 }); + } + + /** + * @param dispatchTarget + * @param name + * @param a1 + * @param a2 + * @return Variant returned by underlying callN + */ + public static Variant call(Dispatch dispatchTarget, String name, Object a1, + Object a2) { + throwIfUnattachedDispatch(dispatchTarget); + return callN(dispatchTarget, name, new Object[] { a1, a2 }); + } + + /** + * @param dispatchTarget + * @param name + * @param a1 + * @param a2 + * @param a3 + * @return Variant returned by underlying callN + */ + public static Variant call(Dispatch dispatchTarget, String name, Object a1, + Object a2, Object a3) { + throwIfUnattachedDispatch(dispatchTarget); + return callN(dispatchTarget, name, new Object[] { a1, a2, a3 }); + } + + /** + * @param dispatchTarget + * @param name + * @param a1 + * @param a2 + * @param a3 + * @param a4 + * @return Variant retuned by underlying callN + */ + public static Variant call(Dispatch dispatchTarget, String name, Object a1, + Object a2, Object a3, Object a4) { + throwIfUnattachedDispatch(dispatchTarget); + return callN(dispatchTarget, name, new Object[] { a1, a2, a3, a4 }); + } + + /** + * @param dispatchTarget + * @param name + * @param a1 + * @param a2 + * @param a3 + * @param a4 + * @param a5 + * @return Variant returned by underlying callN + */ + public static Variant call(Dispatch dispatchTarget, String name, Object a1, + Object a2, Object a3, Object a4, Object a5) { + throwIfUnattachedDispatch(dispatchTarget); + return callN(dispatchTarget, name, new Object[] { a1, a2, a3, a4, a5 }); + } + + /** + * @param dispatchTarget + * @param name + * @param a1 + * @param a2 + * @param a3 + * @param a4 + * @param a5 + * @param a6 + * @return Variant retuned by underlying callN + */ + public static Variant call(Dispatch dispatchTarget, String name, Object a1, + Object a2, Object a3, Object a4, Object a5, Object a6) { + throwIfUnattachedDispatch(dispatchTarget); + return callN(dispatchTarget, name, new Object[] { a1, a2, a3, a4, a5, + a6 }); + } + + /** + * @param dispatchTarget + * @param name + * @param a1 + * @param a2 + * @param a3 + * @param a4 + * @param a5 + * @param a6 + * @param a7 + * @return Variant returned by underlying callN + */ + public static Variant call(Dispatch dispatchTarget, String name, Object a1, + Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { + throwIfUnattachedDispatch(dispatchTarget); + return callN(dispatchTarget, name, new Object[] { a1, a2, a3, a4, a5, + a6, a7 }); + } + + /** + * @param dispatchTarget + * @param name + * @param a1 + * @param a2 + * @param a3 + * @param a4 + * @param a5 + * @param a6 + * @param a7 + * @param a8 + * @return Variant retuned by underlying callN + */ + public static Variant call(Dispatch dispatchTarget, String name, Object a1, + Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, + Object a8) { + throwIfUnattachedDispatch(dispatchTarget); + return callN(dispatchTarget, name, new Object[] { a1, a2, a3, a4, a5, + a6, a7, a8 }); + } + + /** + * @param dispatchTarget + * @param dispid + * @return Variant returned by underlying callN + */ + public static Variant call(Dispatch dispatchTarget, int dispid) { + throwIfUnattachedDispatch(dispatchTarget); + return callN(dispatchTarget, dispid, NO_VARIANT_ARGS); + } + + /** + * @param dispatchTarget + * @param dispid + * @param a1 + * @return Variant returned by underlying callN + */ + public static Variant call(Dispatch dispatchTarget, int dispid, Object a1) { + throwIfUnattachedDispatch(dispatchTarget); + return callN(dispatchTarget, dispid, new Object[] { a1 }); + } + + /** + * @param dispatchTarget + * @param dispid + * @param a1 + * @param a2 + * @return Variant returned by underlying callN + */ + public static Variant call(Dispatch dispatchTarget, int dispid, Object a1, + Object a2) { + throwIfUnattachedDispatch(dispatchTarget); + return callN(dispatchTarget, dispid, new Object[] { a1, a2 }); + } + + /** + * @param dispatchTarget + * @param dispid + * @param a1 + * @param a2 + * @param a3 + * @return Variant returned by underlying callN + */ + public static Variant call(Dispatch dispatchTarget, int dispid, Object a1, + Object a2, Object a3) { + throwIfUnattachedDispatch(dispatchTarget); + return callN(dispatchTarget, dispid, new Object[] { a1, a2, a3 }); + } + + /** + * @param dispatchTarget + * @param dispid + * @param a1 + * @param a2 + * @param a3 + * @param a4 + * @return Variant returned by underlying callN + */ + public static Variant call(Dispatch dispatchTarget, int dispid, Object a1, + Object a2, Object a3, Object a4) { + throwIfUnattachedDispatch(dispatchTarget); + return callN(dispatchTarget, dispid, new Object[] { a1, a2, a3, a4 }); + } + + /** + * @param dispatchTarget + * @param dispid + * @param a1 + * @param a2 + * @param a3 + * @param a4 + * @param a5 + * @return Variant returned by underlying callN + */ + public static Variant call(Dispatch dispatchTarget, int dispid, Object a1, + Object a2, Object a3, Object a4, Object a5) { + throwIfUnattachedDispatch(dispatchTarget); + return callN(dispatchTarget, dispid, + new Object[] { a1, a2, a3, a4, a5 }); + } + + /** + * @param dispatchTarget + * @param dispid + * @param a1 + * @param a2 + * @param a3 + * @param a4 + * @param a5 + * @param a6 + * @return Variant returned by underlying callN + */ + public static Variant call(Dispatch dispatchTarget, int dispid, Object a1, + Object a2, Object a3, Object a4, Object a5, Object a6) { + throwIfUnattachedDispatch(dispatchTarget); + return callN(dispatchTarget, dispid, new Object[] { a1, a2, a3, a4, a5, + a6 }); + } + + /** + * @param dispatchTarget + * @param dispid + * @param a1 + * @param a2 + * @param a3 + * @param a4 + * @param a5 + * @param a6 + * @param a7 + * @return Variant returned by underlying callN + */ + public static Variant call(Dispatch dispatchTarget, int dispid, Object a1, + Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { + throwIfUnattachedDispatch(dispatchTarget); + return callN(dispatchTarget, dispid, new Object[] { a1, a2, a3, a4, a5, + a6, a7 }); + } + + /** + * @param dispatchTarget + * @param dispid + * @param a1 + * @param a2 + * @param a3 + * @param a4 + * @param a5 + * @param a6 + * @param a7 + * @param a8 + * @return Variant returned by underlying callN + */ + public static Variant call(Dispatch dispatchTarget, int dispid, Object a1, + Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, + Object a8) { + throwIfUnattachedDispatch(dispatchTarget); + return callN(dispatchTarget, dispid, new Object[] { a1, a2, a3, a4, a5, + a6, a7, a8 }); + } + + /* + * ============================================================ start of the + * invoke section + * =========================================================== + */ + /** + * @param dispatchTarget + * @param name + * @param val + */ + public static void put(Dispatch dispatchTarget, String name, Object val) { + throwIfUnattachedDispatch(dispatchTarget); + invoke(dispatchTarget, name, Dispatch.Put, new Object[] { val }, + new int[1]); + } + + /** + * @param dispatchTarget + * @param dispid + * @param val + */ + public static void put(Dispatch dispatchTarget, int dispid, Object val) { + throwIfUnattachedDispatch(dispatchTarget); + invoke(dispatchTarget, dispid, Dispatch.Put, new Object[] { val }, + new int[1]); + } + + /* + * ============================================================ start of the + * invokev section + * =========================================================== + */ + // removed _Guid argument + /** + * @param dispatchTarget + * @param name + * @param dispID + * @param lcid + * @param wFlags + * @param vArg + * @param uArgErr + * @return Variant returned by underlying invokev + */ + public static native Variant invokev(Dispatch dispatchTarget, String name, + int dispID, int lcid, int wFlags, Variant[] vArg, int[] uArgErr); + + /** + * @param dispatchTarget + * @param name + * @param wFlags + * @param vArg + * @param uArgErr + * @return Variant returned by underlying invokev + */ + public static Variant invokev(Dispatch dispatchTarget, String name, + int wFlags, Variant[] vArg, int[] uArgErr) { + throwIfUnattachedDispatch(dispatchTarget); + return invokev(dispatchTarget, name, 0, Dispatch.LOCALE_SYSTEM_DEFAULT, + wFlags, vArg, uArgErr); + } + + /** + * @param dispatchTarget + * @param name + * @param wFlags + * @param vArg + * @param uArgErr + * @param wFlagsEx + * @return Variant returned by underlying invokev + */ + public static Variant invokev(Dispatch dispatchTarget, String name, + int wFlags, Variant[] vArg, int[] uArgErr, int wFlagsEx) { + throwIfUnattachedDispatch(dispatchTarget); + // do not implement IDispatchEx for now + return invokev(dispatchTarget, name, 0, Dispatch.LOCALE_SYSTEM_DEFAULT, + wFlags, vArg, uArgErr); + } + + /** + * @param dispatchTarget + * @param dispID + * @param wFlags + * @param vArg + * @param uArgErr + * @return Variant returned by underlying invokev + */ + public static Variant invokev(Dispatch dispatchTarget, int dispID, + int wFlags, Variant[] vArg, int[] uArgErr) { + throwIfUnattachedDispatch(dispatchTarget); + return invokev(dispatchTarget, null, dispID, + Dispatch.LOCALE_SYSTEM_DEFAULT, wFlags, vArg, uArgErr); + } + + /* + * ============================================================ start of the + * invokeSubv section + * =========================================================== + */ + + // removed _Guid argument + /** + * @param dispatchTarget + * @param name + * @param dispid + * @param lcid + * @param wFlags + * @param oArg + * @param uArgErr + */ + public static void invokeSub(Dispatch dispatchTarget, String name, + int dispid, int lcid, int wFlags, Object[] oArg, int[] uArgErr) { + throwIfUnattachedDispatch(dispatchTarget); + invokeSubv(dispatchTarget, name, dispid, lcid, wFlags, + VariantUtilities.objectsToVariants(oArg), uArgErr); + } + + /* + * ============================================================ start of the + * invokeSub section + * =========================================================== + */ + /** + * @param dispatchTarget + * @param name + * @param wFlags + * @param oArg + * @param uArgErr + */ + public static void invokeSub(Dispatch dispatchTarget, String name, + int wFlags, Object[] oArg, int[] uArgErr) { + throwIfUnattachedDispatch(dispatchTarget); + invokeSub(dispatchTarget, name, 0, Dispatch.LOCALE_SYSTEM_DEFAULT, + wFlags, oArg, uArgErr); + } + + /** + * @param dispatchTarget + * @param dispid + * @param wFlags + * @param oArg + * @param uArgErr + */ + public static void invokeSub(Dispatch dispatchTarget, int dispid, + int wFlags, Object[] oArg, int[] uArgErr) { + throwIfUnattachedDispatch(dispatchTarget); + invokeSub(dispatchTarget, null, dispid, Dispatch.LOCALE_SYSTEM_DEFAULT, + wFlags, oArg, uArgErr); + } + + /* + * ============================================================ start of the + * callSubN section + * =========================================================== + */ + /** + * makes call to native callSubN + * + * @param dispatchTarget + * @param name + */ + public static void callSub(Dispatch dispatchTarget, String name) { + throwIfUnattachedDispatch(dispatchTarget); + callSubN(dispatchTarget, name, NO_OBJECT_ARGS); + } + + /** + * makes call to native callSubN + * + * @param dispatchTarget + * @param name + * @param a1 + */ + public static void callSub(Dispatch dispatchTarget, String name, Object a1) { + throwIfUnattachedDispatch(dispatchTarget); + callSubN(dispatchTarget, name, new Object[] { a1 }); + } + + /** + * makes call to native callSubN + * + * @param dispatchTarget + * @param name + * @param a1 + * @param a2 + */ + public static void callSub(Dispatch dispatchTarget, String name, Object a1, + Object a2) { + throwIfUnattachedDispatch(dispatchTarget); + callSubN(dispatchTarget, name, new Object[] { a1, a2 }); + } + + /** + * makes call to native callSubN + * + * @param dispatchTarget + * @param name + * @param a1 + * @param a2 + * @param a3 + */ + public static void callSub(Dispatch dispatchTarget, String name, Object a1, + Object a2, Object a3) { + throwIfUnattachedDispatch(dispatchTarget); + callSubN(dispatchTarget, name, new Object[] { a1, a2, a3 }); + } + + /** + * makes call to native callSubN + * + * @param dispatchTarget + * @param name + * @param a1 + * @param a2 + * @param a3 + * @param a4 + */ + public static void callSub(Dispatch dispatchTarget, String name, Object a1, + Object a2, Object a3, Object a4) { + throwIfUnattachedDispatch(dispatchTarget); + callSubN(dispatchTarget, name, new Object[] { a1, a2, a3, a4 }); + } + + /** + * makes call to native callSubN + * + * @param dispatchTarget + * @param name + * @param a1 + * @param a2 + * @param a3 + * @param a4 + * @param a5 + */ + public static void callSub(Dispatch dispatchTarget, String name, Object a1, + Object a2, Object a3, Object a4, Object a5) { + throwIfUnattachedDispatch(dispatchTarget); + callSubN(dispatchTarget, name, new Object[] { a1, a2, a3, a4, a5 }); + } + + /** + * makes call to native callSubN + * + * @param dispatchTarget + * @param name + * @param a1 + * @param a2 + * @param a3 + * @param a4 + * @param a5 + * @param a6 + */ + public static void callSub(Dispatch dispatchTarget, String name, Object a1, + Object a2, Object a3, Object a4, Object a5, Object a6) { + throwIfUnattachedDispatch(dispatchTarget); + callSubN(dispatchTarget, name, new Object[] { a1, a2, a3, a4, a5, a6 }); + } + + /** + * makes call to native callSubN + * + * @param dispatchTarget + * @param name + * @param a1 + * @param a2 + * @param a3 + * @param a4 + * @param a5 + * @param a6 + * @param a7 + */ + public static void callSub(Dispatch dispatchTarget, String name, Object a1, + Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { + throwIfUnattachedDispatch(dispatchTarget); + callSubN(dispatchTarget, name, new Object[] { a1, a2, a3, a4, a5, a6, + a7 }); + } + + /** + * makes call to native callSubN + * + * @param dispatchTarget + * @param name + * @param a1 + * @param a2 + * @param a3 + * @param a4 + * @param a5 + * @param a6 + * @param a7 + * @param a8 + */ + public static void callSub(Dispatch dispatchTarget, String name, Object a1, + Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, + Object a8) { + throwIfUnattachedDispatch(dispatchTarget); + callSubN(dispatchTarget, name, new Object[] { a1, a2, a3, a4, a5, a6, + a7, a8 }); + } + + /** + * makes call to native callSubN + * + * @param dispatchTarget + * @param dispid + */ + public static void callSub(Dispatch dispatchTarget, int dispid) { + throwIfUnattachedDispatch(dispatchTarget); + callSubN(dispatchTarget, dispid, NO_OBJECT_ARGS); + } + + /** + * makes call to native callSubN + * + * @param dispatchTarget + * @param dispid + * @param a1 + */ + public static void callSub(Dispatch dispatchTarget, int dispid, Object a1) { + throwIfUnattachedDispatch(dispatchTarget); + callSubN(dispatchTarget, dispid, new Object[] { a1 }); + } + + /** + * makes call to native callSubN + * + * @param dispatchTarget + * @param dispid + * @param a1 + * @param a2 + */ + public static void callSub(Dispatch dispatchTarget, int dispid, Object a1, + Object a2) { + throwIfUnattachedDispatch(dispatchTarget); + callSubN(dispatchTarget, dispid, new Object[] { a1, a2 }); + } + + /** + * makes call to native callSubN + * + * @param dispatchTarget + * @param dispid + * @param a1 + * @param a2 + * @param a3 + */ + public static void callSub(Dispatch dispatchTarget, int dispid, Object a1, + Object a2, Object a3) { + callSubN(dispatchTarget, dispid, new Object[] { a1, a2, a3 }); + } + + /** + * makes call to native callSubN + * + * @param dispatchTarget + * @param dispid + * @param a1 + * @param a2 + * @param a3 + * @param a4 + */ + public static void callSub(Dispatch dispatchTarget, int dispid, Object a1, + Object a2, Object a3, Object a4) { + throwIfUnattachedDispatch(dispatchTarget); + callSubN(dispatchTarget, dispid, new Object[] { a1, a2, a3, a4 }); + } + + /** + * makes call to native callSubN + * + * @param dispatchTarget + * @param dispid + * @param a1 + * @param a2 + * @param a3 + * @param a4 + * @param a5 + */ + public static void callSub(Dispatch dispatchTarget, int dispid, Object a1, + Object a2, Object a3, Object a4, Object a5) { + throwIfUnattachedDispatch(dispatchTarget); + callSubN(dispatchTarget, dispid, new Object[] { a1, a2, a3, a4, a5 }); + } + + /** + * makes call to native callSubN + * + * @param dispatchTarget + * @param dispid + * @param a1 + * @param a2 + * @param a3 + * @param a4 + * @param a5 + * @param a6 + */ + public static void callSub(Dispatch dispatchTarget, int dispid, Object a1, + Object a2, Object a3, Object a4, Object a5, Object a6) { + throwIfUnattachedDispatch(dispatchTarget); + callSubN(dispatchTarget, dispid, + new Object[] { a1, a2, a3, a4, a5, a6 }); + } + + /** + * makes call to native callSubN + * + * @param dispatchTarget + * @param dispid + * @param a1 + * @param a2 + * @param a3 + * @param a4 + * @param a5 + * @param a6 + * @param a7 + */ + public static void callSub(Dispatch dispatchTarget, int dispid, Object a1, + Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { + throwIfUnattachedDispatch(dispatchTarget); + callSubN(dispatchTarget, dispid, new Object[] { a1, a2, a3, a4, a5, a6, + a7 }); + } + + /** + * makes call to native callSubN + * + * @param dispatchTarget + * @param dispid + * @param a1 + * @param a2 + * @param a3 + * @param a4 + * @param a5 + * @param a6 + * @param a7 + * @param a8 + */ + public static void callSub(Dispatch dispatchTarget, int dispid, Object a1, + Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, + Object a8) { + callSubN(dispatchTarget, dispid, new Object[] { a1, a2, a3, a4, a5, a6, + a7, a8 }); + } + + /* + * ============================================================ start of the + * invokev section + * =========================================================== + */ + /** + * Cover for call to underlying invokev() + * + * @param dispatchTarget + * @param name + * @return Variant returned by the request for retrieval of parameter + */ + public static Variant get(Dispatch dispatchTarget, String name) { + throwIfUnattachedDispatch(dispatchTarget); + return invokev(dispatchTarget, name, Dispatch.Get, NO_VARIANT_ARGS, + NO_INT_ARGS); + } + + /** + * Cover for call to underlying invokev() + * + * @param dispatchTarget + * @param dispid + * @return Variant returned by the request for retrieval of parameter + */ + public static Variant get(Dispatch dispatchTarget, int dispid) { + throwIfUnattachedDispatch(dispatchTarget); + return invokev(dispatchTarget, dispid, Dispatch.Get, NO_VARIANT_ARGS, + NO_INT_ARGS); + } + + /* + * ============================================================ start of the + * invoke section + * =========================================================== + */ + /** + * cover for underlying call to invoke + * + * @param dispatchTarget + * @param name + * @param val + */ + public static void putRef(Dispatch dispatchTarget, String name, Object val) { + throwIfUnattachedDispatch(dispatchTarget); + invoke(dispatchTarget, name, Dispatch.PutRef, new Object[] { val }, + new int[1]); + } + + /** + * cover for underlying call to invoke + * + * @param dispatchTarget + * @param dispid + * @param val + */ + public static void putRef(Dispatch dispatchTarget, int dispid, Object val) { + throwIfUnattachedDispatch(dispatchTarget); + invoke(dispatchTarget, dispid, Dispatch.PutRef, new Object[] { val }, + new int[1]); + } + + /** + * not implemented yet + * + * @param dispatchTarget + * @param name + * @return Variant never returned + * @throws com.jacob.com.NotImplementedException + */ + public static Variant get_CaseSensitive(Dispatch dispatchTarget, String name) { + throw new NotImplementedException("not implemented yet"); + } + } \ No newline at end of file diff --git a/src/com/jacob/com/DispatchEvents.java b/src/com/jacob/com/DispatchEvents.java index 1551646..a9ca0a1 100644 --- a/src/com/jacob/com/DispatchEvents.java +++ b/src/com/jacob/com/DispatchEvents.java @@ -20,177 +20,200 @@ package com.jacob.com; /** - * This class creates the scaffolding for event callbacks. - * Every instance of tis acts as a wrapper around some java object - * that wants callbacks from the microsoft side. It represents - * the connection between Java and COM for callbacks. + * This class creates the scaffolding for event callbacks. Every instance of tis + * acts as a wrapper around some java object that wants callbacks from the + * microsoft side. It represents the connection between Java and COM for + * callbacks. *

- * The callback mechanism will take any event that it receives and - * try and find a java method with the same name that accepts the - * Variant... as a parameter. It will then wrap the call back data - * in the Variant array and call the java method of the object - * that this DispatchEvents object was initialized with. + * The callback mechanism will take any event that it receives and try and find + * a java method with the same name that accepts the Variant... as a parameter. + * It will then wrap the call back data in the Variant array and call the java + * method of the object that this DispatchEvents object was initialized with. *

- * Instances of this class are created with "sink object" that - * will receive the event messages. The sink object is wrapped in - * an Invocation handler that actually receives the messages and then - * forwards them on to the "sink object". The constructors recognize when - * an instance of InvocationProxy is passed in and do not create - * a new InvocationProxy as a wrapper. They instead use the passed in - * InvocationProxy. + * Instances of this class are created with "sink object" that will receive the + * event messages. The sink object is wrapped in an Invocation handler that + * actually receives the messages and then forwards them on to the "sink + * object". The constructors recognize when an instance of InvocationProxy is + * passed in and do not create a new InvocationProxy as a wrapper. They instead + * use the passed in InvocationProxy. * */ 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. - *

- * Creates the event callback linkage between the the - * MS program represented by the Dispatch object and the - * Java object that will receive the callback. - *

- * 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 ); - } + /** + * 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; - /** - * None of the samples use this constructor. - *

- * Creates the event callback linkage between the the - * MS program represented by the Dispatch object and the - * Java object that will receive the callback. - *

- * 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 ); - } + /** + * 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; - /** - * Creates the event callback linkage between the the - * MS program represented by the Dispatch object and the - * Java object that will receive the callback. - *

- * This method was added because Excel doesn't implement IProvideClassInfo - * and the registry entry for Excel.Application doesn't include a typelib key. - * - *

-     * DispatchEvents de = 
-     * 			new DispatchEvents(someDispatch,someEventHAndler,
-     * 				"Excel.Application",
-     * 				"C:\\Program Files\\Microsoft Office\\OFFICE11\\EXCEL.EXE");
-     * 
- * @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 "); + /** + * This is the most commonly used constructor. + *

+ * Creates the event callback linkage between the the MS program represented + * by the Dispatch object and the Java object that will receive the + * callback. + *

+ * 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. + *

+ * Creates the event callback linkage between the the MS program represented + * by the Dispatch object and the Java object that will receive the + * callback. + *

+ * 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. + *

+ * This method was added because Excel doesn't implement IProvideClassInfo + * and the registry entry for Excel.Application doesn't include a typelib + * key. + * + *

+	 * DispatchEvents de = new DispatchEvents(someDispatch, someEventHAndler,
+	 * 		"Excel.Application",
+	 * 		"C:\\Program Files\\Microsoft Office\\OFFICE11\\EXCEL.EXE");
+	 * 
+ * + * @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) { mInvocationProxy = (InvocationProxy) eventSink; } else { mInvocationProxy = getInvocationProxy(eventSink); } - if (mInvocationProxy != null) { - init3(sourceOfEvent, mInvocationProxy, progId, typeLib); + if (mInvocationProxy != null) { + init3(sourceOfEvent, mInvocationProxy, progId, typeLib); } else { - if (JacobObject.isDebugEnabled()){ + if (JacobObject.isDebugEnabled()) { 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 - * @param pTargetObject - * @return InvocationProxy an instance of the proxy this DispatchEvents will send to the COM layer - */ - protected InvocationProxy getInvocationProxy(Object pTargetObject){ + /** + * Returns an instance of the proxy configured with pTargetObject as its + * target + * + * @param 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(); newProxy.setTarget(pTargetObject); return newProxy; } /** - * hooks up a connection point proxy by progId - * event methods on the sink object will be called - * by name with a signature of (Variant[] args) - * - * You must specify the location of the typeLib. - * - * @param src dispatch that is the source of the messages - * @param sink the object that will receive the messages - * @param progId optional program id. most folks don't need this either - * @param typeLib optional parameter for those programs that don't register their type libs (like Excel) - */ - private native void init3(Dispatch src, Object sink, String progId, String typeLib); + * hooks up a connection point proxy by progId event methods on the sink + * object will be called by name with a signature of (Variant[] args) + * + * You must specify the location of the typeLib. + * + * @param src + * dispatch that is the source of the messages + * @param sink + * the object that will receive the messages + * @param progId + * optional program id. most folks don't need this either + * @param typeLib + * optional parameter for those programs that don't register + * their type libs (like Excel) + */ + private native void init3(Dispatch src, Object sink, String progId, + String typeLib); - /** - * now private so only this object can asccess - * was: call this to explicitly release the com object before gc - * - */ - private native void release(); - - /* - * (non-Javadoc) - * @see java.lang.Object#finalize() - */ - protected void finalize() { - safeRelease(); - } - - /* - * (non-Javadoc) - * @see com.jacob.com.JacobObject#safeRelease() - */ - public void safeRelease(){ - if (mInvocationProxy!=null){ - mInvocationProxy.setTarget(null); - } - mInvocationProxy = null; - super.safeRelease(); - if (m_pConnPtProxy != 0){ - release(); - m_pConnPtProxy = 0; - } else { - // looks like a double release - if (isDebugEnabled()){debug("DispatchEvents:"+this.hashCode()+" double release");} - } - } + /** + * now private so only this object can asccess was: call this to explicitly + * release the com object before gc + * + */ + private native void release(); + + /* + * (non-Javadoc) + * + * @see java.lang.Object#finalize() + */ + protected void finalize() { + safeRelease(); + } + + /* + * (non-Javadoc) + * + * @see com.jacob.com.JacobObject#safeRelease() + */ + public void safeRelease() { + if (mInvocationProxy != null) { + mInvocationProxy.setTarget(null); + } + mInvocationProxy = null; + super.safeRelease(); + if (m_pConnPtProxy != 0) { + release(); + m_pConnPtProxy = 0; + } else { + // looks like a double release + if (isDebugEnabled()) { + debug("DispatchEvents:" + this.hashCode() + " double release"); + } + } + } } diff --git a/src/com/jacob/com/DispatchIdentifier.java b/src/com/jacob/com/DispatchIdentifier.java new file mode 100644 index 0000000..cebd9f8 --- /dev/null +++ b/src/com/jacob/com/DispatchIdentifier.java @@ -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; +} diff --git a/src/com/jacob/com/DispatchProxy.java b/src/com/jacob/com/DispatchProxy.java index e1db537..c8f08cf 100644 --- a/src/com/jacob/com/DispatchProxy.java +++ b/src/com/jacob/com/DispatchProxy.java @@ -29,58 +29,64 @@ package com.jacob.com; * construct a separate DispatchProxy instance for each such case! */ public class DispatchProxy extends JacobObject { - /** - * Comment for m_pStream - */ - public int m_pStream; + /** + * Comment for m_pStream + */ + public int m_pStream; - /** - * Marshals the passed in dispatch into the stream - * @param localDispatch - */ - public DispatchProxy(Dispatch localDispatch) { - MarshalIntoStream(localDispatch); - } + /** + * Marshals the passed in dispatch into the stream + * + * @param localDispatch + */ + public DispatchProxy(Dispatch localDispatch) { + MarshalIntoStream(localDispatch); + } - /** - * - * @return Dispatch the dispatch retrieved from the stream - */ - public Dispatch toDispatch() { - return MarshalFromStream(); - } + /** + * + * @return Dispatch the dispatch retrieved from the stream + */ + public Dispatch toDispatch() { + 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 - * was: call this to explicitly release the com object before gc - * - */ - private native void release(); + /** + * now private so only this object can access was: call this to explicitly + * release the com object before gc + * + */ + private native void release(); - /* (non-Javadoc) - * @see java.lang.Object#finalize() - */ - public void finalize() { - safeRelease(); - } - - /* - * (non-Javadoc) - * @see com.jacob.com.JacobObject#safeRelease() - */ - public void safeRelease() - { - super.safeRelease(); - if (m_pStream != 0){ - release(); - m_pStream = 0; - } else { - // looks like a double release - if (isDebugEnabled()){debug(this.getClass().getName()+":"+this.hashCode()+" double release");} - } - } + /* + * (non-Javadoc) + * + * @see java.lang.Object#finalize() + */ + public void finalize() { + safeRelease(); + } + + /* + * (non-Javadoc) + * + * @see com.jacob.com.JacobObject#safeRelease() + */ + public void safeRelease() { + super.safeRelease(); + if (m_pStream != 0) { + release(); + m_pStream = 0; + } else { + // looks like a double release + if (isDebugEnabled()) { + debug(this.getClass().getName() + ":" + this.hashCode() + + " double release"); + } + } + } } \ No newline at end of file diff --git a/src/com/jacob/com/EnumVariant.java b/src/com/jacob/com/EnumVariant.java index c77923f..8ff298f 100644 --- a/src/com/jacob/com/EnumVariant.java +++ b/src/com/jacob/com/EnumVariant.java @@ -23,121 +23,134 @@ package com.jacob.com; * An implementation of IEnumVariant based on code submitted by Thomas Hallgren * (mailto:Thomas.Hallgren@eoncompany.com) */ -public class EnumVariant extends JacobObject implements java.util.Enumeration { - private int m_pIEnumVARIANT; +public class EnumVariant extends JacobObject implements + java.util.Enumeration { + 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 - // - protected EnumVariant(int pIEnumVARIANT) { - m_pIEnumVARIANT = pIEnumVARIANT; - } + // this only gets called from JNI + // + protected EnumVariant(int pIEnumVARIANT) { + m_pIEnumVARIANT = pIEnumVARIANT; + } - /** - * @param disp - */ - public EnumVariant(Dispatch disp) { - int[] hres = new int[1]; - Variant evv = Dispatch.invokev(disp, - Dispatch.DISPID_NEWENUM, - Dispatch.Get, - new Variant[0], hres); - if (evv.getvt() != Variant.VariantObject) - // - // The DISPID_NEWENUM did not result in a valid object - // - throw new ComFailException("Can't obtain EnumVARIANT"); + /** + * @param disp + */ + public EnumVariant(Dispatch disp) { + int[] hres = new int[1]; + Variant evv = Dispatch.invokev(disp, DispatchIdentifier.DISPID_NEWENUM, + Dispatch.Get, new Variant[0], hres); + if (evv.getvt() != Variant.VariantObject) + // + // The DISPID_NEWENUM did not result in a valid object + // + throw new ComFailException("Can't obtain EnumVARIANT"); - EnumVariant tmp = evv.toEnumVariant(); - m_pIEnumVARIANT = tmp.m_pIEnumVARIANT; - tmp.m_pIEnumVARIANT = 0; - } + EnumVariant tmp = evv.toEnumVariant(); + m_pIEnumVARIANT = tmp.m_pIEnumVARIANT; + tmp.m_pIEnumVARIANT = 0; + } - /** - * Implements java.util.Enumeration - * @return boolean true if there are more elements in ths enumeration - */ - public boolean hasMoreElements() { - { - if (m_recBuf[0] == null) { - if (this.Next(m_recBuf) <= 0) - return false; - } - return true; - } - } + /** + * Implements java.util.Enumeration + * + * @return boolean true if there are more elements in this enumeration + */ + public boolean hasMoreElements() { + { + if (m_recBuf[0] == null) { + if (this.Next(m_recBuf) <= 0) + return false; + } + return true; + } + } - /** - * Implements java.util.Enumeration - * @return next element in the enumeration - */ - public Object nextElement() { - Object last = m_recBuf[0]; - if (last == null) { - if (this.Next(m_recBuf) <= 0) - throw new java.util.NoSuchElementException(); - last = m_recBuf[0]; - } - m_recBuf[0] = null; - return last; - } + /** + * Implements java.util.Enumeration + * + * @return next element in the enumeration + */ + public Variant nextElement() { + Variant last = m_recBuf[0]; + if (last == null) { + if (this.Next(m_recBuf) <= 0) + throw new java.util.NoSuchElementException(); + last = m_recBuf[0]; + } + m_recBuf[0] = null; + return last; + } - /** - * Get next element in collection or null if at end - * @return Variant that is next in the collection - */ - public Variant Next() { - if (hasMoreElements()) - return (Variant) nextElement(); - return null; - } + /** + * Get next element in collection or null if at end + * + * @return Variant that is next in the collection + * @deprecated use nextElement() instead + */ + @Deprecated + public Variant Next() { + if (hasMoreElements()) + return nextElement(); + return null; + } - /** - * @param receiverArray - * @return don't know what the int is that is returned, help! - */ - public native int Next(Variant[] receiverArray); + /** + * This should be private and wrapped to protect JNI layer. + * + * @param receiverArray + * @return Returns the next variant object pointer as an int from windows + * layer + */ + public native int Next(Variant[] receiverArray); - /** - * @param count - */ - public native void Skip(int count); + /** + * This should be private and wrapped to protect JNI layer. + * + * @param count + * number to skip + */ + public native void Skip(int count); - /** - * - */ - public native void Reset(); + /** + * This should be private and wrapped to protect JNI layer + */ + public native void Reset(); - /** - * now private so only this object can asccess - * was: call this to explicitly release the com object before gc - * - */ - private native void release(); + /** + * now private so only this object can access was: call this to explicitly + * release the com object before gc + * + */ + private native void release(); - /* - * (non-Javadoc) - * @see java.lang.Object#finalize() - */ - protected void finalize() - { - safeRelease(); - } - - /* - * (non-Javadoc) - * @see com.jacob.com.JacobObject#safeRelease() - */ - public void safeRelease() - { - super.safeRelease(); - if (m_pIEnumVARIANT != 0){ - this.release(); - m_pIEnumVARIANT = 0; - } else { - // looks like a double release - if (isDebugEnabled()){debug(this.getClass().getName()+":"+this.hashCode()+" double release");} - } - } + /* + * (non-Javadoc) + * + * @see java.lang.Object#finalize() + */ + protected void finalize() { + safeRelease(); + } + + /* + * (non-Javadoc) + * + * @see com.jacob.com.JacobObject#safeRelease() + */ + public void safeRelease() { + super.safeRelease(); + if (m_pIEnumVARIANT != 0) { + this.release(); + m_pIEnumVARIANT = 0; + } else { + // looks like a double release + if (isDebugEnabled()) { + debug(this.getClass().getName() + ":" + this.hashCode() + + " double release"); + } + } + } } \ No newline at end of file diff --git a/src/com/jacob/com/InvocationProxy.java b/src/com/jacob/com/InvocationProxy.java index d2bccec..7687d84 100644 --- a/src/com/jacob/com/InvocationProxy.java +++ b/src/com/jacob/com/InvocationProxy.java @@ -23,20 +23,19 @@ package com.jacob.com; * @version $Id$ * @author joe * - * DispatchEvents wraps this class around any event handlers - * before making the JNI call that sets up the link with EventProxy. - * This means that EventProxy.cpp just calls invoke(String,Variant[]) - * against the instance of this class. Then this class does - * reflection against the event listener to call the actual event methods. - * The event methods can return void or return a Variant. Any - * value returned will be passed back to the calling windows module + * DispatchEvents wraps this class around any event handlers before making the + * JNI call that sets up the link with EventProxy. This means that + * EventProxy.cpp just calls invoke(String,Variant[]) against the instance of + * this class. Then this class does reflection against the event listener to + * call the actual event methods. The event methods can return void or return a + * Variant. Any value returned will be passed back to the calling windows module * by the Jacob JNI layer. *

* - * The void returning signature is the standard legacy signature. - * The Variant returning signature was added in 1.10 to support event handlers - * returning values. - * + * The void returning signature is the standard legacy signature. The Variant + * returning signature was added in 1.10 to support event handlers returning + * values. + * */ public abstract class InvocationProxy { @@ -44,58 +43,66 @@ public abstract class InvocationProxy { * the object we will try and forward to. */ protected Object mTargetObject = null; - + /** - * dummy constructor for subclasses that don't actually wrap - * anything and just want to override the invoke() method + * dummy constructor for subclasses that don't actually wrap anything and + * just want to override the invoke() method */ - protected InvocationProxy(){ + protected InvocationProxy() { 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. - *

- * 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. - * @param pTargetObject - * @throws IllegalArgumentException if target is not publicly accessable - */ - public void setTarget(Object pTargetObject){ - if (JacobObject.isDebugEnabled()){ - JacobObject.debug( - "InvocationProxy: setting target "+pTargetObject); + /** + * 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. + *

+ * 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 + * @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 - // 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? - if (!java.lang.reflect.Modifier.isPublic( - pTargetObject.getClass().getModifiers())){ + if (!java.lang.reflect.Modifier.isPublic(pTargetObject.getClass() + .getModifiers())) { throw new IllegalArgumentException( - "InvocationProxy only public classes can receive event notifications"); + "InvocationProxy only public classes can receive event notifications"); } } mTargetObject = pTargetObject; - } - + } + } diff --git a/src/com/jacob/com/InvocationProxyAllVariants.java b/src/com/jacob/com/InvocationProxyAllVariants.java index e1b3aad..3a5d846 100644 --- a/src/com/jacob/com/InvocationProxyAllVariants.java +++ b/src/com/jacob/com/InvocationProxyAllVariants.java @@ -24,62 +24,69 @@ import java.lang.reflect.Method; /** * This class acts as a proxy between the windows event callback mechanism and - * the Java classes that are looking for events. It assumes that - * all of the Java classes that are looking for events implement methods with the - * same names as the windows events and that the implemented methods accept an - * array of variant objects. The methods can return void or a Variant that - * will be returned to the calling layer. All Event methods that will be - * recognized by InvocationProxyAllEvents have the signature - * - * void eventMethodName(Variant[]) - * or - * Variant eventMethodName(Variant[]) + * the Java classes that are looking for events. It assumes that all of the Java + * classes that are looking for events implement methods with the same names as + * the windows events and that the implemented methods accept an array of + * variant objects. The methods can return void or a Variant that will be + * returned to the calling layer. All Event methods that will be recognized by + * InvocationProxyAllEvents have the signature + * + * void eventMethodName(Variant[]) or + * Variant eventMethodName(Variant[]) */ public class InvocationProxyAllVariants extends InvocationProxy { /* * (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[]) { - Variant mVariantToBeReturned = null; - if (mTargetObject == null){ - if (JacobObject.isDebugEnabled()){ - JacobObject.debug( - "InvocationProxy: received notification ("+methodName+") with no target set"); + Variant mVariantToBeReturned = null; + if (mTargetObject == null) { + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("InvocationProxy: received notification (" + + 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; } Class targetClass = mTargetObject.getClass(); - if (methodName == null){ - throw new IllegalArgumentException("InvocationProxy: missing method name"); + if (methodName == null) { + throw new IllegalArgumentException( + "InvocationProxy: missing method name"); } - if (targetParameters == null){ - throw new IllegalArgumentException("InvocationProxy: missing Variant parameters"); + if (targetParameters == null) { + throw new IllegalArgumentException( + "InvocationProxy: missing Variant parameters"); } try { - if (JacobObject.isDebugEnabled()){ - JacobObject.debug("InvocationProxy: trying to invoke "+methodName - +" on "+mTargetObject); + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("InvocationProxy: trying to invoke " + + methodName + " on " + mTargetObject); } Method targetMethod; targetMethod = targetClass.getMethod(methodName, - new Class[] {Variant[].class}); - if (targetMethod != null){ + new Class[] { Variant[].class }); + if (targetMethod != null) { // 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 Object mReturnedByInvocation = null; - mReturnedByInvocation = - targetMethod.invoke(mTargetObject,new Object[] {targetParameters}); - if (mReturnedByInvocation == null){ + mReturnedByInvocation = targetMethod.invoke(mTargetObject, + new Object[] { targetParameters }); + if (mReturnedByInvocation == null) { mVariantToBeReturned = null; - } else if (!(mReturnedByInvocation instanceof Variant)){ + } else if (!(mReturnedByInvocation instanceof Variant)) { // could try and convert to Variant here. throw new IllegalArgumentException( "InvocationProxy: invokation of target method returned " - +"non-null non-variant object: "+mReturnedByInvocation); + + "non-null non-variant object: " + + mReturnedByInvocation); } else { mVariantToBeReturned = (Variant) mReturnedByInvocation; } @@ -88,20 +95,22 @@ public class InvocationProxyAllVariants extends InvocationProxy { // what causes this exception? e.printStackTrace(); } catch (NoSuchMethodException e) { - // this happens whenever the listener doesn't implement all the methods - if (JacobObject.isDebugEnabled()){ - JacobObject.debug("InvocationProxy: listener ("+mTargetObject+") doesn't implement " - + methodName); + // this happens whenever the listener doesn't implement all the + // methods + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("InvocationProxy: listener (" + mTargetObject + + ") doesn't implement " + methodName); } } catch (IllegalArgumentException e) { 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; } catch (IllegalAccessException e) { // can't access the method on the target instance for some reason - if (JacobObject.isDebugEnabled()){ - JacobObject.debug("InvocationProxy: probably tried to access public method on non public class" - + methodName); + if (JacobObject.isDebugEnabled()) { + JacobObject + .debug("InvocationProxy: probably tried to access public method on non public class" + + methodName); } e.printStackTrace(); } catch (InvocationTargetException e) { @@ -109,6 +118,6 @@ public class InvocationProxyAllVariants extends InvocationProxy { e.printStackTrace(); } return mVariantToBeReturned; - + } } diff --git a/src/com/jacob/com/JacobException.java b/src/com/jacob/com/JacobException.java index 82a14d9..6e2e926 100644 --- a/src/com/jacob/com/JacobException.java +++ b/src/com/jacob/com/JacobException.java @@ -20,9 +20,9 @@ package com.jacob.com; /** - * The parent class of all Jacob exceptions. - * They all used to be based off of RuntimeException or ComException - * but it was decided to base them all off of one owned by this project. + * The parent class of all Jacob exceptions. They all used to be based off of + * RuntimeException or ComException but it was decided to base them all off of + * one owned by this project. */ public class JacobException extends RuntimeException { @@ -32,18 +32,18 @@ public class JacobException extends RuntimeException { private static final long serialVersionUID = -1637125318746002715L; /** - * Default constructor. - * Calls super with a "No Message Provided" string + * Default constructor. Calls super with a "No Message Provided" string */ - public JacobException(){ + public JacobException() { super("No Message Provided"); } - + /** * standard constructor + * * @param message */ - public JacobException(String message){ + public JacobException(String message) { super(message); } } diff --git a/src/com/jacob/com/JacobObject.java b/src/com/jacob/com/JacobObject.java index c350775..4715da9 100644 --- a/src/com/jacob/com/JacobObject.java +++ b/src/com/jacob/com/JacobObject.java @@ -19,17 +19,13 @@ */ 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 - * create a standard API framework and to facillitate memory management - * for Java and COM memory elements. + * The superclass of all Jacob objects. It is used to create a standard API + * framework and to facilitate memory management for Java and COM memory + * elements. *

- * All instances of this class and subclasses are automatically manged - * by the ROT. This means the ROT cannot be a subclass of JacobObject. + * All instances of this class and subclasses are automatically managed by the + * ROT. This means the ROT cannot be a subclass of JacobObject. *

* 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 @@ -39,116 +35,77 @@ import java.util.Properties; public class JacobObject { /** - * holds the build version as retrieved from the version.properties - * file that exists in the JAR. - * This can be retrived by calling the static method getBuildVersion() - * @see getBuildVersion() + * Standard constructor that adds this JacobObject to the memory management + * pool. */ - private static String buildVersion = ""; + public JacobObject() { + ROT.addObject(this); + } + /** - * holds the build date as retrieved from the version.properties - * file that exists in the JAR - * This can be retrived by calling the static method getBuildDate() - * @see getBuildDate() + * Finalizers call this method. This method should release any COM data + * structures in a way that it can be called multiple times. This can happen + * if someone manually calls this and then a finalizer calls it. */ - private static String buildDate = ""; - - /** - * Standard constructor that adds this JacobObject - * to the memory management pool. - */ - public JacobObject() { - ROT.addObject(this); - } + public void safeRelease() { + // currently does nothing - subclasses may do something + if (isDebugEnabled()) { + // this used to do a toString() but that is bad for SafeArray + debug("SafeRelease: " + this.getClass().getName()); + } + } - - /** - * Loads version information from version.properties that was - * built as part of this release. - * - */ - 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; - } + /** + * When things go wrong, it is useful to be able to debug the ROT. + */ + private static final boolean DEBUG = + // true; + "true".equalsIgnoreCase(System.getProperty("com.jacob.debug")); - /** - * loads version.properties and returns the value of versin in it - * @return String value of version in version.properties or "" if none - */ - public static String getBuildVersion(){ - if (buildVersion.equals("")){ - loadVersionProperties(); - } - return buildVersion; - } - - /** - * Finalizers call this method. - * This method should release any COM data structures in a way - * that it can be called multiple times. - * This can happen if someone manually calls this and then - * a finalizer calls it. - */ - public void safeRelease() { - // currently does nothing - subclasses may do something - if (isDebugEnabled()){ - // this used to do a toString() but that is bad for SafeArray - debug("SafeRelease: "+this.getClass().getName()); - } - } - - /** - * When things go wrong, it is usefull to be able to debug the ROT. - */ - private static final boolean DEBUG = - //true; - "true".equalsIgnoreCase(System.getProperty("com.jacob.debug")); - - protected static boolean isDebugEnabled(){ - //return true; - return DEBUG; - } - /** - * Very basic debugging fucntion. - * @param istrMessage - */ - protected static void debug(String istrMessage) - { - if(isDebugEnabled()) - { - System.out.println(istrMessage - + " in thread "+ Thread.currentThread().getName()); - } - } + protected static boolean isDebugEnabled() { + // return true; + return DEBUG; + } + + /** + * Loads JacobVersion.Properties and returns the value of version in it + * + * @deprecated use JacobReleaseInfo.getBuildDate() instead. + * @return String value of version in JacobVersion.Properties or "" if none + */ + @Deprecated + public static String getBuildDate() { + return JacobReleaseInfo.getBuildDate(); + } + + /** + * Loads JacobVersion.Properties and returns the value of version in it + * + * @deprecated use JacobReleaseInfo.getBuildVersion() instead. + * @return String value of version in JacobVersion.Properties or "" if none + */ + @Deprecated + public static String getBuildVersion() { + return JacobReleaseInfo.getBuildVersion(); + } + + /** + * Very basic debugging function. + * + * @param istrMessage + */ + protected static void debug(String istrMessage) { + if (isDebugEnabled()) { + System.out.println(istrMessage + " in thread " + + Thread.currentThread().getName()); + } + } + + /** + * force the jacob DLL to be loaded whenever this class is referenced + */ + static { + LibraryLoader.loadJacobLibrary(); + } - /** - * force the jacob DLL to be loaded whenever this class is referenced - */ - static { - LibraryLoader.loadJacobLibrary(); - } - - } \ No newline at end of file diff --git a/src/com/jacob/com/JacobReleaseInfo.java b/src/com/jacob/com/JacobReleaseInfo.java new file mode 100644 index 0000000..a41b239 --- /dev/null +++ b/src/com/jacob/com/JacobReleaseInfo.java @@ -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; + } + +} diff --git a/src/com/jacob/com/LibraryLoader.java b/src/com/jacob/com/LibraryLoader.java index ef2cfb4..d595a93 100644 --- a/src/com/jacob/com/LibraryLoader.java +++ b/src/com/jacob/com/LibraryLoader.java @@ -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). * Get more information about JACOB at http://sourceforge.net/projects/jacob-project * @@ -19,44 +19,208 @@ */ 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. - * - *

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. *

- * The standard behavior for most applications is that LoadLibrary() will be called - * to load the dll. LoadLibary searches directories specified in the variable - * java.library.path . This is why most test cases specify -Djava.library.path in - * their command line arguments + * + * This supports defining the path or library name using system properties or a + * custom resource file. If desired, jacob can auto-detect the correct version + * of the DLL for 32 or 64 bit windows, as long as you have named them + * differently. + * + *

    + *
  1. If system property {@link #JACOB_DLL_PATH} is defined, the file located + * there will be loaded as the jacob dll using System.load().
  2. + * + *
  3. If system property {@link #JACOB_DLL_NAME} is defined, the file located + * there will be loaded as the jacob dll.
  4. + *
  5. 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.
  6. + * + *
  7. 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}.
  8. + *
  9. 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.
  10. + * + *
  11. If none of the above are true, the default is to load the library named + * "jacob-<version>-<arch>" (or + * "jacob-<version>-<arch&rt;.dll") from the {@code java.library.path}. + *
  12. + *
+ * + * 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. *

- * Submitted sourceforge ticket 1493647 + * JACOB_DLL_PATH submitted sourceforge ticket 1493647 Added 1.11
+ * JACOB_DLL_NAME, JACOB_DLL_NAME_32, JACOB_DLL_NAME_64 submitted sourceforge + * ticket 1845039 Added 1.14M7 + * * @author Scott Dickerson (sjd78) + * @author Jason Smith */ public final class LibraryLoader { /** - * Name of system property (currently jacob.dll.path) that may contain - * an absolute path to the JNI library. + * Name of system property (currently jacob.dll.path) that may + * contain an absolute path to the JNI library. */ public static final String JACOB_DLL_PATH = "jacob.dll.path"; + /** + * Name of system property (currently jacob.dll.name) 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 - * {@link #JACOB_DLL_PATH} or as a general library called "jacob". - * @throws UnsatisfiedLinkError if the library does not exist. + * Name of system property (currently jacob.dll.name) that may + * contain an alternate name for the JNI library (default is 'jacob'), 32 + * bit windows. + */ + public static final String JACOB_DLL_NAME_X86 = "jacob.dll.name.x86"; + + /** + * Name of system property (currently jacob.dll.name) 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() { + // 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 keys = new HashSet(); + try { + resources = ResourceBundle.getBundle(LibraryLoader.class.getName(), + Locale.getDefault(), LibraryLoader.class.getClassLoader()); + for (Enumeration 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); + if (path == null && resources != null && keys.contains(JACOB_DLL_PATH)) { + path = (String) resources.getObject(JACOB_DLL_PATH); + } + if (path != null) { System.load(path); - } - else { - System.loadLibrary("jacob"); + } else { + // Path was not defined, so use the OS mechanism for loading + // libraries. + // Check for a defined NAME. System property overrides resource + // bundle. + String name = null; + + if (System.getProperty(JACOB_DLL_NAME) != null) { + name = System.getProperty(JACOB_DLL_NAME); + } else if (System.getProperty(JACOB_DLL_NAME_X86) != null + && shouldLoad32Bit()) { + name = System.getProperty(JACOB_DLL_NAME_X86); + } else if (System.getProperty(JACOB_DLL_NAME_X64) != null + && !shouldLoad32Bit()) { + name = System.getProperty(JACOB_DLL_NAME_X64); + } else if (resources != null && keys.contains(JACOB_DLL_NAME)) { + name = resources.getString(JACOB_DLL_NAME); + } else if (resources != null && keys.contains(JACOB_DLL_NAME_X86) + && shouldLoad32Bit()) { + name = resources.getString(JACOB_DLL_NAME_X86); + } else if (resources != null && keys.contains(JACOB_DLL_NAME_X64) + && !shouldLoad32Bit()) { + name = resources.getString(JACOB_DLL_NAME_X64); + } else { + // No alternate NAME or PATH was defined, so use the default. + // We will almost always end up here. + name = getPreferredDLLName(); + } + + // 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 + *

+ * The DLL name is "jacob\.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 diff --git a/src/com/jacob/com/MainSTA.java b/src/com/jacob/com/MainSTA.java index 3974ce0..a87e3c4 100644 --- a/src/com/jacob/com/MainSTA.java +++ b/src/com/jacob/com/MainSTA.java @@ -20,10 +20,10 @@ package com.jacob.com; /** - * We provide our own main sta thread to avoid COM tagging a random - * thread as the main STA - this is the thread in which all Apartment - * threaded components will be created if the client chooses an MTA - * threading model for the java side of the app. + * We provide our own main sta thread to avoid COM tagging a random thread as + * the main STA - this is the thread in which all Apartment threaded components + * will be created if the client chooses an MTA threading model for the java + * side of the app. */ public class MainSTA extends STA { } \ No newline at end of file diff --git a/src/com/jacob/com/NotImplementedException.java b/src/com/jacob/com/NotImplementedException.java index 5b41a6e..c5773b5 100644 --- a/src/com/jacob/com/NotImplementedException.java +++ b/src/com/jacob/com/NotImplementedException.java @@ -20,24 +20,22 @@ package com.jacob.com; /** - * Thrown by java APIs that are not implemented either because - * they were never implemented or because they are bieng deprecated - * This is a subclass of ComException so callers can still just catch - * ComException. + * Thrown by java APIs that are not implemented either because they were never + * implemented or because they are being deprecated This is a subclass of + * ComException so callers can still just catch ComException. */ public class NotImplementedException extends JacobException { - /** + /** * */ private static final long serialVersionUID = -9169900832852356445L; /** - * @param description - */ - public NotImplementedException(String description) { - super(description); - } + * @param description + */ + public NotImplementedException(String description) { + super(description); + } - } diff --git a/src/com/jacob/com/ROT.java b/src/com/jacob/com/ROT.java index 2551579..f71ba4e 100644 --- a/src/com/jacob/com/ROT.java +++ b/src/com/jacob/com/ROT.java @@ -28,194 +28,210 @@ import java.util.WeakHashMap; * 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 * current thread so all the methods are static and they implicitly get the - * current thread. + * current thread. *

- * The clearObjects method is used to release all the COM objects created by Jacob - * in the current thread prior to uninitializing COM for that thread. + * The clearObjects method is used to release all the COM objects created by + * Jacob in the current thread prior to uninitializing COM for that thread. *

* 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 - * allows the objects referenced by the ROT to be automatically GCed. - * Automatic GC may be preferable in systems with heavy event callbacks. + * from 1.9 onward, setting the com.jacob.autogc system property allows the + * objects referenced by the ROT to be automatically GCed. Automatic GC may be + * preferable in systems with heavy event callbacks. *

* Is [ 1116101 ] jacob-msg 0284 relevant??? */ public abstract class ROT { /** - * Manual garbage collection was the only option pre 1.9 - * Can staticly cache the results because only one value - * and we don't let it change during a run + * Manual garbage collection was the only option pre 1.9 Can staticly cache + * the results because only one value and we don't let it change during a + * run */ - protected static final boolean USE_AUTOMATIC_GARBAGE_COLLECTION = - "true".equalsIgnoreCase( System.getProperty( "com.jacob.autogc" ) ); + protected static final boolean USE_AUTOMATIC_GARBAGE_COLLECTION = "true" + .equalsIgnoreCase(System.getProperty("com.jacob.autogc")); /** - * Suffix added to class name to make up property name that determines if this - * object should be stored in the ROT. This 1.13 "feature" makes it possible - * to cause VariantViaEvent objects to not be added to the ROT in event callbacks. + * Suffix added to class name to make up property name that determines if + * this object should be stored in the ROT. This 1.13 "feature" makes it + * possible to cause VariantViaEvent objects to not be added to the ROT in + * event callbacks. *

- * We don't have a static for the actual property because there is a different property - * for each class that may make use of this feature. + * We don't have a static for the actual property because there is a + * 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 - * HashMap that represents a thread. - * Each thread HashMap contains the com objects created - * in that thread + * A hash table where each element is another HashMap that represents a + * thread. Each thread HashMap contains the com objects created in that + * thread */ - private static HashMap rot = new HashMap(); + private static HashMap> rot = new HashMap>(); /** * adds a new thread storage area to rot + * * @return Map corresponding to the thread that this call was made in */ - protected synchronized static Map addThread() { - // should use the id here instead of the name because the name can be changed + protected synchronized static Map addThread() { + // should use the id here instead of the name because the name can be + // changed String t_name = Thread.currentThread().getName(); - if ( rot.containsKey( t_name ) ) { + if (rot.containsKey(t_name)) { // nothing to do } else { - Map tab = null; - if ( JacobObject.isDebugEnabled() ) { - JacobObject.debug( "ROT: Automatic GC flag == " + USE_AUTOMATIC_GARBAGE_COLLECTION ); + Map tab = null; + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("ROT: Automatic GC flag == " + + USE_AUTOMATIC_GARBAGE_COLLECTION); } - if ( !USE_AUTOMATIC_GARBAGE_COLLECTION ) { - tab = new HashMap(); + if (!USE_AUTOMATIC_GARBAGE_COLLECTION) { + tab = new HashMap(); } else { - tab = new WeakHashMap(); + tab = new WeakHashMap(); } - 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 - * one if you wish by passing in TRUE + * returns the pool for this thread if it exists. can create a new one if + * you wish by passing in TRUE + * * @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 getThreadObjects( + boolean createIfDoesNotExist) { String t_name = Thread.currentThread().getName(); - if ( !rot.containsKey( t_name ) && createIfDoesNotExist ) { + if (!rot.containsKey(t_name) && createIfDoesNotExist) { addThread(); } - return (Map) rot.get( t_name ); + return rot.get(t_name); } /** - * Iterates across all of the entries in the Hashmap in the rot - * that corresponds to this thread. - * This calls safeRelease() on each entry and then - * clears the map when done and removes it from the rot. - * All traces of this thread's objects will disapear. - * This is called by COMThread in the tear down and provides a - * synchronous way of releasing memory + * Iterates across all of the entries in the Hashmap in the rot that + * corresponds to this thread. This calls safeRelease() on each entry and + * then clears the map when done and removes it from the rot. All traces of + * this thread's objects will disapear. This is called by COMThread in the + * tear down and provides a synchronous way of releasing memory */ protected synchronized static void clearObjects() { - Map tab = getThreadObjects( false ); - if ( JacobObject.isDebugEnabled() ) { - JacobObject.debug( "ROT: " + rot.keySet().size() + " thread tables exist" ); + Map tab = getThreadObjects(false); + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("ROT: " + rot.keySet().size() + + " thread tables exist"); } - if ( tab != null ) { - if ( JacobObject.isDebugEnabled() ) { - JacobObject.debug( "ROT: " + tab.keySet().size() + " objects to clear in this thread " ); + if (tab != null) { + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("ROT: " + tab.keySet().size() + + " objects to clear in this thread "); } // walk the values - Iterator it = tab.keySet().iterator(); - while ( it.hasNext() ) { - JacobObject o = (JacobObject) it.next(); - if ( o != null - // can't use this cause creates a Variant if calling SafeAray - // and we get an exceptin modifying the collection while iterating + Iterator it = tab.keySet().iterator(); + while (it.hasNext()) { + JacobObject o = it.next(); + if (o != null + // can't use this cause creates a Variant if calling SafeAray + // and we get an exception modifying the collection while + // iterating // && o.toString() != null ) { - if ( JacobObject.isDebugEnabled() ) { - if ( o instanceof SafeArray ) { - // SafeArray create more objects when calling toString() - // which causes a concurrent modification exception in HashMap - JacobObject.debug( "ROT: removing " + o.getClass().getName() ); + if (JacobObject.isDebugEnabled()) { + if (o instanceof SafeArray) { + // SafeArray create more objects when calling + // toString() + // which causes a concurrent modification exception + // in HashMap + JacobObject.debug("ROT: removing " + + o.getClass().getName()); } else { // 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(); } - // 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 tab.clear(); // remove the collection from rot - rot.remove( Thread.currentThread().getName() ); - if ( JacobObject.isDebugEnabled() ) { - JacobObject.debug( "ROT: thread table cleared and removed" ); + rot.remove(Thread.currentThread().getName()); + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("ROT: thread table cleared and removed"); } } else { - if ( JacobObject.isDebugEnabled() ) { - JacobObject.debug( "ROT: nothing to clear!" ); + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("ROT: nothing to clear!"); } } } /** - * @deprecated the java model leave the responsibility of clearing up objects - * to the Garbage Collector. Our programming model should not require that the - * user specifically remove object from the thread. + * @deprecated the java model leave the responsibility of clearing up + * objects to the Garbage Collector. Our programming model + * should not require that the user specifically remove object + * from the thread. * * This will remove an object from the ROT * @param o */ - protected synchronized static void removeObject( JacobObject o ) { + @Deprecated + protected synchronized static void removeObject(JacobObject o) { String t_name = Thread.currentThread().getName(); - Map tab = (Map) rot.get( t_name ); - if ( tab != null ) { - tab.remove( o ); + Map tab = rot.get(t_name); + if (tab != null) { + tab.remove(o); } o.safeRelease(); } /** * adds an object to the HashMap for the current thread + * * @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 // the default value is "true" which simulates the old behavior - String shouldIncludeClassInROT = - System.getProperty(o.getClass().getName() + PUT_IN_ROT_SUFFIX,"true"); - if (shouldIncludeClassInROT.equalsIgnoreCase("false")){ - if (JacobObject.isDebugEnabled()){ - JacobObject.debug("JacobObject: New instance of "+o.getClass().getName()+" not added to ROT"); - } - } else { - Map tab = getThreadObjects( false ); - if ( tab == null ) { + String shouldIncludeClassInROT = System.getProperty(o.getClass() + .getName() + + PUT_IN_ROT_SUFFIX, "true"); + if (shouldIncludeClassInROT.equalsIgnoreCase("false")) { + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("JacobObject: New instance of " + + o.getClass().getName() + " not added to ROT"); + } + } else { + Map tab = getThreadObjects(false); + if (tab == null) { // this thread has not been initialized as a COM thread // so make it part of MTA for backwards compatibility - ComThread.InitMTA( false ); - tab = getThreadObjects( true ); + ComThread.InitMTA(false); + tab = getThreadObjects(true); } - if ( JacobObject.isDebugEnabled() ) { - JacobObject.debug( - "ROT: adding " + o + "->" + o.getClass().getName() + - " table size prior to addition:" + tab.size() ); + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("ROT: adding " + o + "->" + + o.getClass().getName() + + " table size prior to addition:" + tab.size()); } - if ( tab != null ) { - tab.put( o, null ); + if (tab != null) { + tab.put(o, null); } - } + } } /** - * ROT can't be a subclass of JacobObject because of the way ROT pools are managed - * so we force a DLL load here by referncing JacobObject + * ROT can't be a subclass of JacobObject because of the way ROT pools are + * managed so we force a DLL load here by referencing JacobObject */ static { LibraryLoader.loadJacobLibrary(); } } - diff --git a/src/com/jacob/com/STA.java b/src/com/jacob/com/STA.java index 64b62b0..837e2d3 100644 --- a/src/com/jacob/com/STA.java +++ b/src/com/jacob/com/STA.java @@ -25,74 +25,77 @@ package com.jacob.com; * component that wants to run in an STA other than the main STA. */ public class STA extends Thread { - /** - * referenced by STA.cpp - */ - public int threadID; + /** + * referenced by STA.cpp + */ + public int threadID; - /** - * constructor for STA - */ - public STA() { - start(); // start the thread - } + /** + * constructor for STA + */ + public STA() { + start(); // start the thread + } - /* (non-Javadoc) - * @see java.lang.Thread#run() - */ - public void run() { - // init COM - ComThread.InitSTA(); - if (OnInit()) { - // this call blocks in the win32 message loop - // until quitMessagePump is called - doMessagePump(); - } - OnQuit(); - // uninit COM - ComThread.Release(); - } + /* + * (non-Javadoc) + * + * @see java.lang.Thread#run() + */ + public void run() { + // init COM + ComThread.InitSTA(); + if (OnInit()) { + // this call blocks in the win32 message loop + // until quitMessagePump is called + doMessagePump(); + } + OnQuit(); + // uninit COM + ComThread.Release(); + } - /** - * 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 - * the thread. - * @return always returns true - */ - public boolean OnInit() { - return true; - } + /** + * 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 + * the thread. + * + * @return always returns true + */ + public boolean OnInit() { + return true; + } - /** - * Override this method to destroy any resource before the thread exits and - * COM in uninitialized - */ - public void OnQuit() { - // there is nothing to see here - } + /** + * Override this method to destroy any resource before the thread exits and + * COM in uninitialized + */ + public void OnQuit() { + // there is nothing to see here + } - /** - * calls quitMessagePump - */ - public void quit() { - quitMessagePump(); - } + /** + * calls quitMessagePump + */ + public void quit() { + quitMessagePump(); + } - /** - * run a message pump for the main STA - */ - public native void doMessagePump(); + /** + * run a message pump for the main STA + */ + public native void doMessagePump(); - /** - * quit message pump for the main STA - */ - public native void quitMessagePump(); + /** + * quit message pump for the main STA + */ + public native void quitMessagePump(); - /** - * STA isn't a subclass of JacobObject so a reference to it doesn't load - * the DLL without this - */ - static { - LibraryLoader.loadJacobLibrary(); - } + /** + * STA isn't a subclass of JacobObject so a reference to it doesn't load the + * DLL without this + */ + static { + LibraryLoader.loadJacobLibrary(); + } } \ No newline at end of file diff --git a/src/com/jacob/com/SafeArray.java b/src/com/jacob/com/SafeArray.java index 83839c6..f250d81 100644 --- a/src/com/jacob/com/SafeArray.java +++ b/src/com/jacob/com/SafeArray.java @@ -20,50 +20,62 @@ package com.jacob.com; /** - * This creates an array wrapper around Variant objects(?). - * Lookslike it supports 1 and two dimensional arrays + * This creates an array wrapper around Variant objects(?). This supports 1, 2 + * and n-dimensional arrays. It exists in this form because n-dimensional arrays + * were a later addition. */ public class SafeArray extends JacobObject { - int m_pV = 0; + /** The super secret int that is actually the pointer to windows memory */ + int m_pV = 0; - /** - * constructor - * - */ - public SafeArray() { - } - - /** - * constructor - * @param vt - */ - public SafeArray(int vt) { - init(vt, new int[] { 0 }, new int[] { -1 }); - } - - /** - * constructor - * @param vt - * @param celems - */ - public SafeArray(int vt, int celems) { - init(vt, new int[] { 0 }, new int[] { celems }); - } - - /** - * @param vt - * @param celems1 - * @param celems2 - */ - public SafeArray(int vt, int celems1, int celems2) { - init(vt, new int[] { 0, 0 }, new int[] { celems1, celems2 }); - } - - /** - * constructor (needs more java doc) + /** + * Constructor. Why does this exist? Yeah, someone will post on sourceforge + * about this comment. * - * With the addition of N-dimensional array support + */ + public SafeArray() { + } + + /** + * Constructor. * + * @param vt + * type of array + */ + public SafeArray(int vt) { + init(vt, new int[] { 0 }, new int[] { -1 }); + } + + /** + * Constructor for a single dimensional array whose lower bounds is 0 and + * whose upper bound is specified as a parameter + * + * @param vt + * type of the array + * @param celems + * length of the array + */ + public SafeArray(int vt, int celems) { + init(vt, new int[] { 0 }, new int[] { celems }); + } + + /** + * Creates a two dimensional SafeArray whose base indexes are 0. + * + * @param vt + * Type of the array + * @param celems1 + * length of the array in first dimension + * @param celems2 + * length of the array in second dimension + */ + public SafeArray(int vt, int celems1, int celems2) { + init(vt, new int[] { 0, 0 }, new int[] { celems1, celems2 }); + } + + /** + * Constructor with support for N-dimensional array support + *

* You create an N-D SafeArray by: SafeArray sa = new * SafeArray(Variant.VariantVariant, new int[] {0,0,0,0}, new int[] * {4,4,4,4}); Where the 1st array is lower bounds and 2nd has the lengths @@ -73,807 +85,1088 @@ public class SafeArray extends JacobObject { * @param lbounds * @param celems */ - public SafeArray(int vt, int lbounds[], int celems[]) { - init(vt, lbounds, celems); - } - - /** - * convert a string to a VT_UI1 array - * @param s source string - */ - public SafeArray(String s) { - char[] ca = s.toCharArray(); - init(Variant.VariantByte, new int[] { 0 }, new int[] { ca.length }); - fromCharArray(ca); - } - - protected native void init(int vt, int lbounds[], int celems[]); - - /** - * not impl - * @return 0 - */ - public int getNumLocks() { - return 0; - } - - /** - * convert a VT_UI1 array to string - * @return variant byte as a string - */ - public String asString() { - if (getvt() != Variant.VariantByte) - return null; - char ja[] = toCharArray(); - return new String(ja); - } - - public native Object clone(); - - - /** - * now private so only this object can asccess - * was: call this to explicitly release the com object before gc - * - */ - private native void destroy(); - - public native int getvt(); - - /* - * (non-Javadoc) - * @see java.lang.Object#finalize() - */ - protected void finalize() { - safeRelease(); - } - - /* - * (non-Javadoc) - * @see com.jacob.com.JacobObject#safeRelease() - */ - public void safeRelease() - { - super.safeRelease(); - if (m_pV != 0){ - destroy(); - m_pV = 0; - } else { - // looks like a double release - if (isDebugEnabled()){debug(this.getClass().getName()+":"+this.hashCode()+" double release");} - } - } - - public native void reinit(SafeArray sa); - - public native void reinterpretType(int vt); - - public native int getLBound(); - - public native int getLBound(int dim); - - public native int getUBound(); - - public native int getUBound(int dim); - - public native int getNumDim(); - - public native int getFeatures(); - - public native int getElemSize(); - - /** - * populate the safe array from the passed in array of data - * @param ja - */ - public native void fromCharArray(char ja[]); - - /** - * populate the safe array from the passed in array of data - * @param ja - */ - public native void fromIntArray(int ja[]); - - /** - * populate the safe array from the passed in array of data - * @param ja - */ - public native void fromShortArray(short ja[]); - - /** - * populate the safe array from the passed in array of data - * @param ja - */ - public native void fromDoubleArray(double ja[]); - - /** - * populate the safe array from the passed in array of data - * @param ja - */ - public native void fromStringArray(String ja[]); - - /** - * populate the safe array from the passed in array of data - * @param ja - */ - public native void fromByteArray(byte ja[]); - - /** - * populate the safe array from the passed in array of data - * @param ja - */ - public native void fromFloatArray(float ja[]); - - /** - * populate the safe array from the passed in array of data - * @param ja - */ - public native void fromBooleanArray(boolean ja[]); - - /** - * populate the safe array from the passed in array of data - * @param ja - */ - public native void fromVariantArray(Variant ja[]); - - /** - * Retrieves the data from the array cast to a Java data type - * @return char[] character array contained in this collection - */ - public native char[] toCharArray(); - - /** - * Retrieves the data from the array cast to a Java data type - * @return int[] int array contained in this collection - */ - public native int[] toIntArray(); - - /** - * Retrieves the data from the array cast to a Java data type - * @return short[] short array contained in this collection - */ - public native short[] toShortArray(); - - /** - * Retrieves the data from the array cast to a Java data type - * @return double[] double array contained in this colleciton - */ - public native double[] toDoubleArray(); - - /** - * Retrieves the data from the array cast to a Java data type - * @return String[] String array contained in this collecition - */ - public native String[] toStringArray(); - - /** - * Retrieves the data from the array cast to a Java data type - * @return byte[] byte array contained in this collecition - */ - public native byte[] toByteArray(); - - /** - * Retrieves the data from the array cast to a Java data type - * @return float[] array of float contained in this collection - */ - public native float[] toFloatArray(); - - /** - * Retrieves the data from the array cast to a Java data type - * @return boolean[] array of booleans contained in this collection - */ - public native boolean[] toBooleanArray(); - - /** - * Retrieves the data from the array cast to a Java data type - * @return Variant[] array of variants contained in this collection - */ - public native Variant[] toVariantArray(); - - /** - * char access - * @param sa_idx - * @return single character rpeesentation - */ - public native char getChar(int sa_idx); - - /** - * char access - * @param sa_idx1 - * @param sa_idx2 - * @return single character repesentation - */ - public native char getChar(int sa_idx1, int sa_idx2); - - /** - * char access - * @param sa_idx - * @param c - */ - public native void setChar(int sa_idx, char c); - - /** - * char access - * @param sa_idx1 - * @param sa_idx2 - * @param c - */ - public native void setChar(int sa_idx1, int sa_idx2, char c); - - /** - * char access - * @param sa_idx - * @param nelems - * @param ja - * @param ja_start - */ - public native void getChars(int sa_idx, int nelems, char ja[], int ja_start); - - /** - * char access - * @param sa_idx - * @param nelems - * @param ja - * @param ja_start - */ - public native void setChars(int sa_idx, int nelems, char ja[], int ja_start); - - /** - * get int from an single dimensional array - * @param sa_idx array index - * @return int stored in array - */ - public native int getInt(int sa_idx); - - /** - * get int from 2 dimensional array - * @param sa_idx1 array index first dimension - * @param sa_idx2 array index of second dimension - * @return int stored in array - */ - public native int getInt(int sa_idx1, int sa_idx2); - - /** - * sets the int value of an element in a single dimensional array - * @param sa_idx index into the array - * @param c the value to be set - */ - public native void setInt(int sa_idx, int c); - - /** - * sets the int value of a 2 dimensional array - * @param sa_idx1 index on the first dimension - * @param sa_idx2 index on the second dimension - * @param c the value to be set - */ - public native void setInt(int sa_idx1, int sa_idx2, int c); - - /** - * retrieves a group of ints from a single dimensional array - * - * @param sa_idx the index in the array to start the get - * @param nelems number of elements to retrieve - * @param ja the structure to be filled with the ints - * @param ja_start the start point in the java int array to start filling - */ - public native void getInts(int sa_idx, int nelems, int ja[], int ja_start); - - /** - * sets a group of ints into a single dimensional array - * @param sa_idx the index of the start of the array to put into - * @param nelems number of elements to be copied - * @param ja the new int values to be put into the array - * @param ja_start the start index in the array that we are copying into SafeArray - */ - public native void setInts(int sa_idx, int nelems, int ja[], int ja_start); - - /** - * short access - * @param sa_idx - * @return short stored in array - */ - public native short getShort(int sa_idx); - - /** - * short access - * @param sa_idx1 - * @param sa_idx2 - * @return short stored in array - */ - public native short getShort(int sa_idx1, int sa_idx2); - - /** - * short access - * @param sa_idx - * @param c - */ - public native void setShort(int sa_idx, short c); - - /** - * short access - * @param sa_idx1 - * @param sa_idx2 - * @param c - */ - public native void setShort(int sa_idx1, int sa_idx2, short c); - - /** - * short access - * @param sa_idx - * @param nelems - * @param ja - * @param ja_start - */ - public native void getShorts(int sa_idx, int nelems, short ja[], - int ja_start); - - /** - * short access - * @param sa_idx - * @param nelems - * @param ja - * @param ja_start - */ - public native void setShorts(int sa_idx, int nelems, short ja[], - int ja_start); - - /** - * double access - * @param sa_idx - * @return double stored in array - */ - public native double getDouble(int sa_idx); - - /** - * double access - * @param sa_idx1 - * @param sa_idx2 - * @return double storedin array - */ - public native double getDouble(int sa_idx1, int sa_idx2); - - /** - * double access - * @param sa_idx - * @param c - */ - public native void setDouble(int sa_idx, double c); - - /** - * double access - * @param sa_idx1 - * @param sa_idx2 - * @param c - */ - public native void setDouble(int sa_idx1, int sa_idx2, double c); - - /** - * double access - * @param sa_idx - * @param nelems - * @param ja - * @param ja_start - */ - public native void getDoubles(int sa_idx, int nelems, double ja[], - int ja_start); - - /** - * double access - * @param sa_idx - * @param nelems - * @param ja - * @param ja_start - */ - public native void setDoubles(int sa_idx, int nelems, double ja[], - int ja_start); - - /** - * string access - * @param sa_idx - * @return String stored in array - * - */ - public native String getString(int sa_idx); - - /** - * string access - * @param sa_idx1 - * @param sa_idx2 - * @return String stored in array - */ - public native String getString(int sa_idx1, int sa_idx2); - - /** - * puts a string into an element in a single dimensional safe array - * @param sa_idx - * @param c - */ - public native void setString(int sa_idx, String c); - - /** - * puts a string into an element in a two dimensional array. - * @param sa_idx1 - * @param sa_idx2 - * @param c - */ - public native void setString(int sa_idx1, int sa_idx2, String c); - - /** - * string access - * @param sa_idx - * @param nelems - * @param ja - * @param ja_start - */ - public native void getStrings(int sa_idx, int nelems, String ja[], - int ja_start); - - /** - * string access - * @param sa_idx - * @param nelems - * @param ja - * @param ja_start - */ - public native void setStrings(int sa_idx, int nelems, String ja[], - int ja_start); - - /** - * byte access - * @param sa_idx - * @return byte representaton - */ - public native byte getByte(int sa_idx); - - /** - * byte access - * @param sa_idx1 - * @param sa_idx2 - * @return byte representation - */ - public native byte getByte(int sa_idx1, int sa_idx2); - - /** - * byte access - * @param sa_idx - * @param c - */ - public native void setByte(int sa_idx, byte c); - - /** - * byte access - * @param sa_idx1 - * @param sa_idx2 - * @param c - */ - public native void setByte(int sa_idx1, int sa_idx2, byte c); - - /** - * Fills byte array from contents of this array - * @param sa_idx - * @param nelems - * @param ja - * @param ja_start - */ - public native void getBytes(int sa_idx, int nelems, byte ja[], int ja_start); - - /** - * fills array with passed in bytes - * @param sa_idx - * @param nelems - * @param ja - * @param ja_start - */ - public native void setBytes(int sa_idx, int nelems, byte ja[], int ja_start); - - /** - * float access - * @param sa_idx - * @return float held in array at location - */ - public native float getFloat(int sa_idx); - - /** - * float access - * @param sa_idx1 - * @param sa_idx2 - * @return float held in array at location - */ - public native float getFloat(int sa_idx1, int sa_idx2); - - /** - * float access - * @param sa_idx - * @param c - */ - public native void setFloat(int sa_idx, float c); - - /** - * float access - * @param sa_idx1 - * @param sa_idx2 - * @param c - */ - public native void setFloat(int sa_idx1, int sa_idx2, float c); - - /** - * float access - * @param sa_idx - * @param nelems - * @param ja - * @param ja_start - */ - public native void getFloats(int sa_idx, int nelems, float ja[], - int ja_start); - - /** - * float access - * @param sa_idx - * @param nelems - * @param ja - * @param ja_start - */ - public native void setFloats(int sa_idx, int nelems, float ja[], - int ja_start); - - /** - * boolean access - * @param sa_idx - * @return boolean representation - */ - public native boolean getBoolean(int sa_idx); - - /** - * boolean access - * @param sa_idx1 - * @param sa_idx2 - * @return boolean representation - */ - public native boolean getBoolean(int sa_idx1, int sa_idx2); - - /** - * boolean access - * @param sa_idx - * @param c - */ - public native void setBoolean(int sa_idx, boolean c); - - /** - * boolean access - * @param sa_idx1 - * @param sa_idx2 - * @param c - */ - public native void setBoolean(int sa_idx1, int sa_idx2, boolean c); - - /** - * boolean access - * @param sa_idx - * @param nelems - * @param ja - * @param ja_start - */ - public native void getBooleans(int sa_idx, int nelems, boolean ja[], - int ja_start); - - /** - * boolean access - * @param sa_idx - * @param nelems - * @param ja - * @param ja_start - */ - public native void setBooleans(int sa_idx, int nelems, boolean ja[], - int ja_start); - - /** - * variant access - * @param sa_idx - * @return Variant held in locatioon in the array? - */ - public native Variant getVariant(int sa_idx); - - /** - * variant access - * @param sa_idx1 - * @param sa_idx2 - * @return Variant held in a location in the array? - */ - public native Variant getVariant(int sa_idx1, int sa_idx2); - - /** - * variant access - * @param sa_idx - * @param c - */ - public native void setVariant(int sa_idx, Variant c); - - /** - * variant access - * @param sa_idx1 - * @param sa_idx2 - * @param c - */ - public native void setVariant(int sa_idx1, int sa_idx2, Variant c); - - /** - * variant access - * @param sa_idx - * @param nelems - * @param ja - * @param ja_start - */ - public native void getVariants(int sa_idx, int nelems, Variant ja[], - int ja_start); - - /** - * variant access - * @param sa_idx - * @param nelems - * @param ja - * @param ja_start - */ - public native void setVariants(int sa_idx, int nelems, Variant ja[], - int ja_start); - - /** - * Standard toString() - * Warning, this creates new Variant objects! - * @return String contents of varaint - */ - public String toString() { - String s = ""; - int ndim = getNumDim(); - if (ndim == 1) { - int ldim = getLBound(); - int udim = getUBound(); - for (int i = ldim; i <= udim; i++) { - Variant v = getVariant(i); - - if (((v.getvt() & Variant.VariantTypeMask) | Variant.VariantArray) == v - .getvt()) { - return s + "[" + v.toSafeArray().toString() + "]"; - } else { - s += " " + v.toString(); - } - } - } else if (ndim == 2) { - int ldim1 = getLBound(1); - int udim1 = getUBound(1); - - int ldim2 = getLBound(2); - int udim2 = getUBound(2); - - for (int i = ldim1; i <= udim1; i++) { - for (int j = ldim2; j <= udim2; j++) { - Variant v = getVariant(i, j); - s += " " + v.toString(); - } - s += "\n"; - } - } - return s; - } - - /*================================================================ - * The beginning of N-dimensional array support - *================================================================*/ - - /** - * get Variant value from N-dimensional array - * @param indices - length must equal Dimension of SafeArray - */ - public native Variant getVariant(int indices[]); - - /** - * set Variant value in N-dimensional array - * @param indices - length must equal Dimension of SafeArray - * @param v - */ - public native void setVariant(int indices[], Variant v); - - - /** - * get char value from N-dimensional array - * @param indices - length must equal Dimension of SafeArray - */ - public native char getChar(int indices[]); - - /** - * set char value in N-dimensional array - * @param indices - length must equal Dimension of SafeArray - * @param c - */ - public native void setChar(int indices[], char c); - - /** - * get int value from N-dimensional array - * @param indices - length must equal Dimension of SafeArray - */ - public native int getInt(int indices[]); - - /** - * set int value in N-dimensional array - * @param indices - length must equal Dimension of SafeArray - * @param c - */ - public native void setInt(int indices[], int c); - - /** - * get short value from N-dimensional array - * @param indices - length must equal Dimension of SafeArray - */ - public native short getShort(int indices[]); - - /** - * set short value in N-dimensional array - * @param indices - length must equal Dimension of SafeArray - * @param c - */ - public native void setShort(int indices[], short c); - - /** - * get double value from N-dimensional array - * @param indices - length must equal Dimension of SafeArray - */ - public native double getDouble(int indices[]); - - /** - * set double value in N-dimensional array - * @param indices - length must equal Dimension of SafeArray - * @param c - */ - public native void setDouble(int indices[], double c); - - /** - * get String value from N-dimensional array - * @param indices - length must equal Dimension of SafeArray - */ - public native String getString(int indices[]); - - /** - * set Stringvalue in N-dimensional array - * @param indices - length must equal Dimension of SafeArray - * @param c - */ - public native void setString(int indices[], String c); - - /** - * get byte value from N-dimensional array - * @param indices - length must equal Dimension of SafeArray - */ - public native byte getByte(int indices[]); - - /** - * set byte value in N-dimensional array - * @param indices - length must equal Dimension of SafeArray - * @param c - */ - public native void setByte(int indices[], byte c); - - /** - * get float value from N-dimensional array - * @param indices - length must equal Dimension of SafeArray - */ - public native float getFloat(int indices[]); - - /** - * set float value in N-dimensional array - * @param indices - length must equal Dimension of SafeArray - * @param c - */ - public native void setFloat(int indices[], float c); - - /** - * get boolean value from N-dimensional array - * @param indices - length must equal Dimension of SafeArray - */ - public native boolean getBoolean(int indices[]); - /** - * set boolean value in N-dimensional array - * @param indices - length must equal Dimension of SafeArray - * @param c - */ - public native void setBoolean(int indices[], boolean c); - + public SafeArray(int vt, int lbounds[], int celems[]) { + init(vt, lbounds, celems); + } + + /** + * convert a string to a VT_UI1 array + * + * @param s + * source string + */ + public SafeArray(String s) { + char[] ca = s.toCharArray(); + init(Variant.VariantByte, new int[] { 0 }, new int[] { ca.length }); + fromCharArray(ca); + } + + /** + * convert a VT_UI1 array to string + * + * @return variant byte as a string + */ + public String asString() { + if (getvt() != Variant.VariantByte) { + return null; + } + char ja[] = toCharArray(); + return new String(ja); + } + + public native Object clone(); + + /** + * now private so only this object can access. Was: call this to explicitly + * release the com object before gc + * + */ + private native void destroy(); + + /** + * {@inheritDoc} + */ + protected void finalize() { + safeRelease(); + } + + /** + * populate the safe array from the passed in array of data + * + * @param ja + */ + public native void fromBooleanArray(boolean ja[]); + + /** + * populate the safe array from the passed in array of data + * + * @param ja + */ + public native void fromByteArray(byte ja[]); + + /** + * populate the safe array from the passed in array of data + * + * @param ja + */ + public native void fromCharArray(char ja[]); + + /** + * populate the safe array from the passed in array of data + * + * @param ja + */ + public native void fromDoubleArray(double ja[]); + + /** + * populate the safe array from the passed in array of data + * + * @param ja + */ + public native void fromFloatArray(float ja[]); + + /** + * populate the safe array from the passed in array of data + * + * @param ja + */ + public native void fromIntArray(int ja[]); + + /** + * populate the safe array from the passed in array of data + * + * @param ja + */ + public native void fromLongArray(long ja[]); + + /** + * populate the safe array from the passed in array of data + * + * @param ja + */ + public native void fromShortArray(short ja[]); + + /** + * populate the safe array from the passed in array of data + * + * @param ja + */ + public native void fromStringArray(String ja[]); + + /** + * populate the safe array from the passed in array of data + * + * @param ja + */ + public native void fromVariantArray(Variant ja[]); + + /** + * boolean access + * + * @param sa_idx + * @return boolean representation + */ + public native boolean getBoolean(int sa_idx); + + /** + * get boolean value from N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @return the value at the specified location + */ + public native boolean getBoolean(int indices[]); + + /** + * boolean access + * + * @param sa_idx1 + * @param sa_idx2 + * @return boolean representation + */ + public native boolean getBoolean(int sa_idx1, int sa_idx2); + + /** + * boolean access + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void getBooleans(int sa_idx, int nelems, boolean ja[], + int ja_start); + + /** + * byte access + * + * @param sa_idx + * @return byte representaton + */ + public native byte getByte(int sa_idx); + + /** + * get byte value from N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @return the value at the specified location + */ + public native byte getByte(int indices[]); + + /** + * byte access + * + * @param sa_idx1 + * @param sa_idx2 + * @return byte representation + */ + public native byte getByte(int sa_idx1, int sa_idx2); + + /** + * Fills byte array from contents of this array + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void getBytes(int sa_idx, int nelems, byte ja[], int ja_start); + + /** + * char access + * + * @param sa_idx + * @return single character rpeesentation + */ + public native char getChar(int sa_idx); + + /** + * get char value from N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @return the value at the specified location + */ + public native char getChar(int indices[]); + + /** + * char access + * + * @param sa_idx1 + * @param sa_idx2 + * @return single character representation + */ + public native char getChar(int sa_idx1, int sa_idx2); + + /** + * char access + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void getChars(int sa_idx, int nelems, char ja[], int ja_start); + + /** + * double access + * + * @param sa_idx + * @return double stored in array + */ + public native double getDouble(int sa_idx); + + /** + * get double value from N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @return the value at the specified location + */ + public native double getDouble(int indices[]); + + /** + * double access + * + * @param sa_idx1 + * @param sa_idx2 + * @return double stored in array + */ + public native double getDouble(int sa_idx1, int sa_idx2); + + /** + * double access + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void getDoubles(int sa_idx, int nelems, double ja[], + int ja_start); + + /** + * @return the size of each element? + */ + public native int getElemSize(); + + /** + * @return The ??features of the array? + */ + public native int getFeatures(); + + /** + * float access + * + * @param sa_idx + * @return float held in array at location + */ + public native float getFloat(int sa_idx); + + /** + * get float value from N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @return the value at the specified location + */ + public native float getFloat(int indices[]); + + /** + * float access + * + * @param sa_idx1 + * @param sa_idx2 + * @return float held in array at location + */ + public native float getFloat(int sa_idx1, int sa_idx2); + + /** + * float access + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void getFloats(int sa_idx, int nelems, float ja[], + int ja_start); + + /** + * get int from an single dimensional array + * + * @param sa_idx + * array index + * @return int stored in array + */ + public native int getInt(int sa_idx); + + /** + * get int value from N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @return the value at the specified location + */ + public native int getInt(int indices[]); + + /** + * get int from 2 dimensional array + * + * @param sa_idx1 + * array index first dimension + * @param sa_idx2 + * array index of second dimension + * @return int stored in array + */ + public native int getInt(int sa_idx1, int sa_idx2); + + /** + * retrieves a group of ints from a single dimensional array + * + * @param sa_idx + * the index in the array to start the get + * @param nelems + * number of elements to retrieve + * @param ja + * the structure to be filled with the ints + * @param ja_start + * the start point in the java int array to start filling + */ + public native void getInts(int sa_idx, int nelems, int ja[], int ja_start); + + /** + * get int from an single dimensional array + * + * @param sa_idx + * array index + * @return long stored in array + */ + public native long getLong(int sa_idx); + + /** + * get long value from N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @return the value at the specified location + */ + public native long getLong(int indices[]); + + /** + * get long from 2 dimensional array + * + * @param sa_idx1 + * array index first dimension + * @param sa_idx2 + * array index of second dimension + * @return long stored in array + */ + public native long getLong(int sa_idx1, int sa_idx2); + + /** + * retrieves a group of longs from a single dimensional array + * + * @param sa_idx + * the index in the array to start the get + * @param nelems + * number of elements to retrieve + * @param ja + * the structure to be filled with the longs + * @param ja_start + * the start point in the java longs array to start filling + */ + public native void getLongs(int sa_idx, int nelems, long ja[], int ja_start); + + /** + * @return The lower bounds of the array? + */ + public native int getLBound(); + + /** + * @param dim + * the dimension we are checking in a multidimensional array + * @return The lower bounds of the array? + */ + public native int getLBound(int dim); + + /** + * @return The number of dimensions in this array + */ + public native int getNumDim(); + + /** + * not implemented. + * + * @return 0 + */ + public int getNumLocks() { + return 0; + } + + /** + * short access + * + * @param sa_idx + * @return short stored in array + */ + public native short getShort(int sa_idx); + + /** + * get short value from N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @return the value at the specified location + */ + public native short getShort(int indices[]); + + /** + * short access + * + * @param sa_idx1 + * @param sa_idx2 + * @return short stored in array + */ + public native short getShort(int sa_idx1, int sa_idx2); + + /** + * short access + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void getShorts(int sa_idx, int nelems, short ja[], + int ja_start); + + /** + * string access + * + * @param sa_idx + * @return String stored in array + * + */ + public native String getString(int sa_idx); + + /** + * get String value from N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @return the value at the specified location + */ + public native String getString(int indices[]); + + /** + * string access + * + * @param sa_idx1 + * @param sa_idx2 + * @return String stored in array + */ + public native String getString(int sa_idx1, int sa_idx2); + + /** + * string access + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void getStrings(int sa_idx, int nelems, String ja[], + int ja_start); + + /** + * @return The upper bounds of the array? + */ + public native int getUBound(); + + /** + * @param dim + * the dimension we are checking in a multidimensional array + * @return The upper bounds of the array? + */ + public native int getUBound(int dim); + + /** + * variant access + * + * @param sa_idx + * @return Variant held in location in the array? + */ + public native Variant getVariant(int sa_idx); + + /** + * get Variant value from N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @return the value at the specified location + */ + public native Variant getVariant(int indices[]); + + /** + * variant access + * + * @param sa_idx1 + * @param sa_idx2 + * @return Variant held in a location in the array? + */ + public native Variant getVariant(int sa_idx1, int sa_idx2); + + /** + * variant access + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void getVariants(int sa_idx, int nelems, Variant ja[], + int ja_start); + + /** + * @return the Variant type + */ + public native int getvt(); + + protected native void init(int vt, int lbounds[], int celems[]); + + /** + * Does anyone want to document this? + * + * @param sa + */ + public native void reinit(SafeArray sa); + + /** + * Does anyone want to document this? + * + * @param vt + * the variant type? + */ + public native void reinterpretType(int vt); + + /** + * {@inheritDoc} + */ + public void safeRelease() { + super.safeRelease(); + if (m_pV != 0) { + destroy(); + m_pV = 0; + } else { + // looks like a double release + if (isDebugEnabled()) { + debug(this.getClass().getName() + ":" + this.hashCode() + + " double release"); + } + } + } + + /** + * boolean access + * + * @param sa_idx + * @param c + */ + public native void setBoolean(int sa_idx, boolean c); + + /** + * set boolean value in N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @param c + */ + public native void setBoolean(int indices[], boolean c); + + /** + * boolean access + * + * @param sa_idx1 + * @param sa_idx2 + * @param c + */ + public native void setBoolean(int sa_idx1, int sa_idx2, boolean c); + + /** + * boolean access + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void setBooleans(int sa_idx, int nelems, boolean ja[], + int ja_start); + + /** + * byte access + * + * @param sa_idx + * @param c + */ + public native void setByte(int sa_idx, byte c); + + /** + * set byte value in N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @param c + */ + public native void setByte(int indices[], byte c); + + /** + * byte access + * + * @param sa_idx1 + * @param sa_idx2 + * @param c + */ + public native void setByte(int sa_idx1, int sa_idx2, byte c); + + /** + * fills array with passed in bytes + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void setBytes(int sa_idx, int nelems, byte ja[], int ja_start); + + /** + * char access + * + * @param sa_idx + * @param c + */ + public native void setChar(int sa_idx, char c); + + /** + * set char value in N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @param c + */ + public native void setChar(int indices[], char c); + + /** + * char access + * + * @param sa_idx1 + * @param sa_idx2 + * @param c + */ + public native void setChar(int sa_idx1, int sa_idx2, char c); + + /** + * char access + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void setChars(int sa_idx, int nelems, char ja[], int ja_start); + + /** + * double access + * + * @param sa_idx + * @param c + */ + public native void setDouble(int sa_idx, double c); + + /** + * set double value in N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @param c + */ + public native void setDouble(int indices[], double c); + + /** + * double access + * + * @param sa_idx1 + * @param sa_idx2 + * @param c + */ + public native void setDouble(int sa_idx1, int sa_idx2, double c); + + /** + * double access + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void setDoubles(int sa_idx, int nelems, double ja[], + int ja_start); + + /** + * float access + * + * @param sa_idx + * @param c + */ + public native void setFloat(int sa_idx, float c); + + /** + * set float value in N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @param c + */ + public native void setFloat(int indices[], float c); + + /** + * float access + * + * @param sa_idx1 + * @param sa_idx2 + * @param c + */ + public native void setFloat(int sa_idx1, int sa_idx2, float c); + + /** + * float access + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void setFloats(int sa_idx, int nelems, float ja[], + int ja_start); + + /** + * sets the int value of an element in a single dimensional array + * + * @param sa_idx + * index into the array + * @param c + * the value to be set + */ + public native void setInt(int sa_idx, int c); + + /** + * set int value in N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @param c + */ + public native void setInt(int indices[], int c); + + /** + * sets the int value of a 2 dimensional array + * + * @param sa_idx1 + * index on the first dimension + * @param sa_idx2 + * index on the second dimension + * @param c + * the value to be set + */ + public native void setInt(int sa_idx1, int sa_idx2, int c); + + /** + * sets a group of ints into a single dimensional array + * + * @param sa_idx + * the index of the start of the array to put into + * @param nelems + * number of elements to be copied + * @param ja + * the new int values to be put into the array + * @param ja_start + * the start index in the array that we are copying into + * SafeArray + */ + public native void setInts(int sa_idx, int nelems, int ja[], int ja_start); + + /** + * sets the long value of an element in a single dimensional array + * + * @param sa_idx + * index into the array + * @param c + * the value to be set + */ + public native void setLong(int sa_idx, long c); + + /** + * set long value in N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @param c + */ + public native void setLong(int indices[], long c); + + /** + * sets the long value of a 2 dimensional array + * + * @param sa_idx1 + * index on the first dimension + * @param sa_idx2 + * index on the second dimension + * @param c + * the value to be set + */ + public native void setLong(int sa_idx1, int sa_idx2, long c); + + /** + * sets a group of longs into a single dimensional array + * + * @param sa_idx + * the index of the start of the array to put into + * @param nelems + * number of elements to be copied + * @param ja + * the new long values to be put into the array + * @param ja_start + * the start index in the array that we are copying into + * SafeArray + */ + public native void setLongs(int sa_idx, int nelems, long ja[], int ja_start); + + /** + * short access + * + * @param sa_idx1 + * @param sa_idx2 + * @param c + */ + public native void setShort(int sa_idx1, int sa_idx2, short c); + + /** + * short access + * + * @param sa_idx + * @param c + */ + public native void setShort(int sa_idx, short c); + + /** + * set short value in N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @param c + */ + public native void setShort(int indices[], short c); + + /** + * short access + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void setShorts(int sa_idx, int nelems, short ja[], + int ja_start); + + /** + * puts a string into an element in a two dimensional array. + * + * @param sa_idx1 + * @param sa_idx2 + * @param c + */ + public native void setString(int sa_idx1, int sa_idx2, String c); + + /* + * ================================================================ The + * beginning of N-dimensional array support + * ================================================================ + */ + + /** + * puts a string into an element in a single dimensional safe array + * + * @param sa_idx + * @param c + */ + public native void setString(int sa_idx, String c); + + /** + * set Stringvalue in N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @param c + */ + public native void setString(int indices[], String c); + + /** + * string access + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void setStrings(int sa_idx, int nelems, String ja[], + int ja_start); + + /** + * variant access + * + * @param sa_idx1 + * @param sa_idx2 + * @param c + */ + public native void setVariant(int sa_idx1, int sa_idx2, Variant c); + + /** + * variant access + * + * @param sa_idx + * @param c + */ + public native void setVariant(int sa_idx, Variant c); + + /** + * set Variant value in N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @param v + */ + public native void setVariant(int indices[], Variant v); + + /** + * variant access + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void setVariants(int sa_idx, int nelems, Variant ja[], + int ja_start); + + /** + * Retrieves the data from the array cast to a Java data type + * + * @return boolean[] array of booleans contained in this collection + */ + public native boolean[] toBooleanArray(); + + /** + * Retrieves the data from the array cast to a Java data type + * + * @return byte[] byte array contained in this collection + */ + public native byte[] toByteArray(); + + /** + * Retrieves the data from the array cast to a Java data type + * + * @return char[] character array contained in this collection + */ + public native char[] toCharArray(); + + /** + * Retrieves the data from the array cast to a Java data type + * + * @return double[] double array contained in this collection + */ + public native double[] toDoubleArray(); + + /** + * Retrieves the data from the array cast to a Java data type + * + * @return float[] array of float contained in this collection + */ + public native float[] toFloatArray(); + + /** + * Retrieves the data from the array cast to a Java data type + * + * @return int[] int array contained in this collection + */ + public native int[] toIntArray(); + + /** + * Retrieves the data from the array cast to a Java data type + * + * @return long[] long array contained in this collection + */ + public native long[] toLongArray(); + + /** + * Retrieves the data from the array cast to a Java data type + * + * @return short[] short array contained in this collection + */ + public native short[] toShortArray(); + + /** + * Standard toString() Warning, this creates new Variant objects! + * + * @return String contents of variant + */ + public String toString() { + String s = ""; + int ndim = getNumDim(); + if (ndim == 1) { + int ldim = getLBound(); + int udim = getUBound(); + for (int i = ldim; i <= udim; i++) { + Variant v = getVariant(i); + + if (((v.getvt() & Variant.VariantTypeMask) | Variant.VariantArray) == v + .getvt()) { + return s + "[" + v.toSafeArray().toString() + "]"; + } else { + s += " " + v.toString(); + } + } + } else if (ndim == 2) { + int ldim1 = getLBound(1); + int udim1 = getUBound(1); + + int ldim2 = getLBound(2); + int udim2 = getUBound(2); + + for (int i = ldim1; i <= udim1; i++) { + for (int j = ldim2; j <= udim2; j++) { + Variant v = getVariant(i, j); + s += " " + v.toString(); + } + s += "\n"; + } + } + return s; + } + + /** + * Retrieves the data from the array cast to a Java data type + * + * @return String[] String array contained in this collection + */ + public native String[] toStringArray(); + + /** + * Retrieves the data from the array cast to a Java data type + * + * @return Variant[] array of variants contained in this collection + */ + public native Variant[] toVariantArray(); + } \ No newline at end of file diff --git a/src/com/jacob/com/Variant.java b/src/com/jacob/com/Variant.java index ba5e586..8c058b3 100644 --- a/src/com/jacob/com/Variant.java +++ b/src/com/jacob/com/Variant.java @@ -19,9 +19,9 @@ */ package com.jacob.com; -import java.util.Date; import java.math.BigDecimal; import java.math.BigInteger; +import java.util.Date; /** * The multi-format data type used for all call backs and most communications @@ -30,442 +30,807 @@ import java.math.BigInteger; *

* Just loading this class creates 3 variants that get added to the ROT *

- * PROPVARIANT introduces new types so eventually Variant will need to be + * PROPVARIANT introduces new types so eventually Variant will need to be * upgraded to support PropVariant types. * http://blogs.msdn.com/benkaras/archive/2006/09/13/749962.aspx *

- * This object no longer implements Serializable because serialization is broken - * (and has been since 2000/xp). The underlying - * marshalling/unmarshalling code is broken in the JNI layer. + * This object no longer implements Serializable because serialization is broken + * (and has been since 2000/xp). The underlying marshalling/unmarshalling code + * is broken in the JNI layer. */ public class Variant extends JacobObject { /** - * Use this constant for optional parameters - */ - public final static com.jacob.com.Variant DEFAULT; + * Use this constant for optional parameters + */ + public final static com.jacob.com.Variant DEFAULT; - /** - * Same than {@link #DEFAULT} - */ - public final static com.jacob.com.Variant VT_MISSING; - - /** - * Use for true/false variant parameters - */ - public final static com.jacob.com.Variant VT_TRUE = new com.jacob.com.Variant( - true); + /** + * Same than {@link #DEFAULT} + */ + public final static com.jacob.com.Variant VT_MISSING; - /** - * Use for true/false variant parameters - */ - public final static com.jacob.com.Variant VT_FALSE = new com.jacob.com.Variant( - false); + /** + * Use for true/false variant parameters + */ + public final static com.jacob.com.Variant VT_TRUE = new com.jacob.com.Variant( + true); - /* - * do the run time definition of DEFAULT and MISSING - * Have to use static block because of the way the initialization si done - */ - static { - com.jacob.com.Variant vtMissing = new com.jacob.com.Variant(); - vtMissing.putVariantNoParam(); - DEFAULT = vtMissing; - VT_MISSING = vtMissing; - } - - /** - * Pointer to MS struct. - */ - int m_pVariant = 0; + /** + * Use for true/false variant parameters + */ + public final static com.jacob.com.Variant VT_FALSE = new com.jacob.com.Variant( + false); - /** variant's type is empty : equivalent to VB Nothing and VT_EMPTY*/ - public static final short VariantEmpty = 0; + /** variant's type is empty : equivalent to VB Nothing and VT_EMPTY */ + public static final short VariantEmpty = 0; - /** variant's type is null : equivalent to VB Null and VT_NULL */ - public static final short VariantNull = 1; + /** variant's type is null : equivalent to VB Null and VT_NULL */ + public static final short VariantNull = 1; - /** variant's type is short VT_I2*/ - public static final short VariantShort = 2; + /** variant's type is short VT_I2 */ + public static final short VariantShort = 2; - /** variant's type is int VT_I4, a Long in VC*/ - public static final short VariantInt = 3; + /** variant's type is int VT_I4, a Long in VC */ + public static final short VariantInt = 3; - /** variant's type is float VT_R4*/ - public static final short VariantFloat = 4; + /** variant's type is float VT_R4 */ + public static final short VariantFloat = 4; - /** variant's type is double VT_R8*/ - public static final short VariantDouble = 5; + /** variant's type is double VT_R8 */ + public static final short VariantDouble = 5; - /** variant's type is currency VT_CY */ - public static final short VariantCurrency = 6; + /** variant's type is currency VT_CY */ + public static final short VariantCurrency = 6; - /** variant's type is date VT_DATE */ - public static final short VariantDate = 7; + /** variant's type is date VT_DATE */ + public static final short VariantDate = 7; - /** variant's type is string also known as VT_BSTR */ - public static final short VariantString = 8; + /** variant's type is string also known as VT_BSTR */ + public static final short VariantString = 8; - /** variant's type is dispatch VT_DISPATCH*/ - public static final short VariantDispatch = 9; + /** variant's type is dispatch VT_DISPATCH */ + public static final short VariantDispatch = 9; - /** variant's type is error VT_ERROR */ - public static final short VariantError = 10; + /** variant's type is error VT_ERROR */ + public static final short VariantError = 10; - /** variant's type is boolean VT_BOOL */ - public static final short VariantBoolean = 11; + /** variant's type is boolean VT_BOOL */ + public static final short VariantBoolean = 11; - /** variant's type is variant it encapsulate another variant VT_VARIANT*/ - public static final short VariantVariant = 12; + /** variant's type is variant it encapsulate another variant VT_VARIANT */ + public static final short VariantVariant = 12; - /** variant's type is object VT_UNKNOWN*/ - public static final short VariantObject = 13; + /** variant's type is object VT_UNKNOWN */ + public static final short VariantObject = 13; - /** variant's type is object VT_DECIMAL*/ - public static final short VariantDecimal = 14; + /** variant's type is object VT_DECIMAL */ + public static final short VariantDecimal = 14; - /** variant's type is byte VT_UI1 */ - public static final short VariantByte = 17; - - /** - * variant's type is 64 bit long integer VT_I8 - - * not yet implemented in Jacob because we have to decide what to do with Currency - * and because its only supported on XP and later. No win2k, NT or 2003 server. - **/ - public static final short VariantLongInt = 20; + /** variant's type is byte VT_UI1 */ + public static final short VariantByte = 17; - /** what is this? */ - public static final short VariantTypeMask = 4095; + /** + * variant's type is 64 bit long integer VT_I8 - not yet implemented in + * Jacob because we have to decide what to do with Currency and because its + * only supported on XP and later. No win2k, NT or 2003 server. + */ + public static final short VariantLongInt = 20; - /** variant's type is array */ - public static final short VariantArray = 8192; + /** what is this? */ + public static final short VariantTypeMask = 4095; - /** variant's type is a reference (to IDispatch?) */ - public static final short VariantByref = 16384; + /** variant's type is array */ + public static final short VariantArray = 8192; - /** - * @deprecated should use changeType() followed by getInt() - * @return the value of this variant as an int - * (after possible conversion) - */ - public int toInt(){ - changeType(VariantInt); - return getInt(); - } + /** variant's type is a reference (to IDispatch?) */ + public static final short VariantByref = 16384; - /** - * @deprecated should use changeType() followed by getDate() - * @return the value of this variant as a date - * (after possible conversion) - */ - public double toDate(){ - changeType(VariantDate); - return getDate(); - } - - /** - * Returns the windows time contained in this Variant as a Java Date - * converts to a date like many of the other toXXX() methods - * SF 959382. - *

- * This method added 12/2005 for possible use by jacobgen instead of its conversion code - *

- * This does not convert the data - * @deprecated callers should use getDate() - * @return java.util.Date version of this variant if it is a date, otherwise null - * - */ - public Date toJavaDate(){ - changeType(Variant.VariantDate); - return getJavaDate(); - } - - - /** - * @deprecated should be replaced by changeType() followed by getBoolean() - * @return the value of this variant as boolean (after possible conversion) - */ - public boolean toBoolean(){ - changeType(Variant.VariantBoolean); - return getBoolean(); - } - - /** @return the value of this variant as an enumeration (java style) */ - public native EnumVariant toEnumVariant(); - - /** - * This method would have returned null if the type was VT_NULL. - * But because we return null if the data is not of the right type, - * this method should have always returned null - * @deprecated method never did anything - */ - public void getNull() {}; - - /** - * Set this Variant's type to VT_NULL (the VB equivalent of NULL) - * */ - private native void putVariantNull(); - - /** - * Set this Variant's type to VT_NULL (the VB equivalent of NULL) - * */ - public void putNull(){ - // verify we aren't released yet - getvt(); - putVariantNull(); - } - - /** - * @deprecated No longer used - * @return null ! - */ - public native Variant cloneIndirect(); - - /** - * @deprecated should call changeType() then getDouble() - * @return the content of this variant as a double - * (after possible conversion) - **/ - public double toDouble(){ - changeType(Variant.VariantDouble); - return getDouble(); - } - - /** - * @deprecated should be replaced by changeType() followed by getCurrency - * @return the content of this variant as a long reprensenting a monetary - * amount - */ - public long toCurrency(){ - changeType(Variant.VariantCurrency); - return getCurrency(); - } - - /** - * @deprecated superceded by SafeArray - * @param in doesn't matter because this method does nothing - * @throws com.jacob.com.NotImplementedException - */ - public void putVariantArray(Variant[] in) { - throw new NotImplementedException("Not implemented"); - } - - /** - * @deprecated superceded by SafeArray - * @return never returns anything - * @throws com.jacob.com.NotImplementedException - */ - public Variant[] getVariantArray() { - throw new NotImplementedException("Not implemented"); - } - - /** - * Exists to support jacobgen. - * This would be deprecated if it weren't for jacobgen - * @deprecated superceded by "this" - * @return this same object - */ - public Variant toVariant() { return this; } - - /** - * @deprecated superceded by SafeArray - * @param in doesn't matter because this method does nothing - * @throws com.jacob.com.NotImplementedException - */ - public void putByteArray(Object in) { - throw new NotImplementedException("Not implemented"); - } - - /** - * set the content of this variant to a short (VT_I2|VT_BYREF) - * @param in - */ - private native void putVariantShortRef(short in); - - /** - * set the content of this variant to a short (VT_I2|VT_BYREF) - * @param in - */ - public void putShortRef(short in){ - // verify we aren't released - getvt(); - putVariantShortRef(in); - } - - /** - * set the content of this variant to an int (VT_I4|VT_BYREF) - * @param in - */ - private native void putVariantIntRef(int in); - - /** - * set the content of this variant to an int (VT_I4|VT_BYREF) - * @param in - */ - public void putIntRef(int in){ - // verify we aren't released - getvt(); - putVariantIntRef(in); - } - - /** - * private JNI method called by putDecimalRef - * @param signum sign - * @param scale BigDecimal's scale - * @param lo low 32 bits - * @param mid middle 32 bits - * @param hi high 32 bits - */ - private native void putVariantDecRef(int signum, byte scale, int lo, int mid, int hi); - - /** - * Set the content of this variant to an decimal (VT_DECIMAL|VT_BYREF) - * This may throw exceptions more often than the caller expects because - * most callers don't manage the scale of their BigDecimal objects. - * @param in the BigDecimal that will be converted to VT_DECIMAL - * @throws IllegalArgumentException if the scale is > 28, the maximum for VT_DECIMAL - */ - public void putDecimalRef(BigDecimal in) { - // verify we aren't released - getvt(); - if (in.scale() > 28) { - // should this really cast to a string and call putStringRef()? - throw new IllegalArgumentException( - "VT_DECIMAL only supports a scale of 28 and the passed" - + " in value has a scale of " + in.scale()); - } else { - byte scale = (byte) in.scale(); - BigInteger unscaled = in.unscaledValue(); - BigInteger shifted = unscaled.shiftRight(32); - putVariantDecRef(in.signum(), scale, unscaled.intValue(), shifted - .intValue(), shifted.shiftRight(32).intValue()); - } + /* + * Do the run time definition of DEFAULT and MISSING. Have to use static + * block because of the way the initialization is done via two calls instead + * of just a constructor for this type. + */ + static { + com.jacob.com.Variant vtMissing = new com.jacob.com.Variant(); + vtMissing.putVariantNoParam(); + DEFAULT = vtMissing; + VT_MISSING = vtMissing; } + /** + * Pointer to MS struct. + */ + int m_pVariant = 0; - /** - * set the content of this variant to a double (VT_R8|VT_BYREF) + /** + * public constructor, initializes and sets type to VariantEmpty + */ + public Variant() { + this(null, false); + } + + /** + * Constructor that accepts a primitive rather than an object * * @param in */ - private native void putVariantDoubleRef(double in); - - /** - * set the content of this variant to a double (VT_R8|VT_BYREF) - * @param in - */ - public void putDoubleRef(double in){ - // verify we aren't released - getvt(); - putVariantDoubleRef(in); - } + public Variant(boolean in) { + this(new Boolean(in)); + } - /** - * set the content of this variant to a date (VT_DATE|VT_BYREF) - * @param in - */ - private native void putVariantDateRef(double in); - - /** - * set the content of this variant to a date (VT_DATE|VT_BYREF) - * @param in - */ - public void putDateRef(double in){ - // verify we aren't released - getvt(); - putVariantDateRef(in); - } - - /** - * converts a java date to a windows time and calls putDateRef(double) - * SF 959382 - * @throws IllegalArgumentException if inDate = null - * @param inDate a Java date to be converted - */ - public void putDateRef(Date inDate){ - if (inDate == null){ - throw new IllegalArgumentException("Cannot put null in as windows date"); - // do nothing - } else { - putDateRef(DateUtilities.convertDateToWindowsTime(inDate)); - } - } - - /** - * set the content of this variant to a string (VT_BSTR|VT_BYREF) - * @param in - */ - private native void putVariantStringRef(String in); - - /** - * set the content of this variant to a string (VT_BSTR|VT_BYREF) - * @param in - */ - public void putStringRef(String in){ - // verify we aren't released - getvt(); - putVariantStringRef(in); - } - /** - * Puts a variant into this variant making it type VT_VARIANT. - * Added 1.12 pre 6 + * Constructor that accepts a primitive rather than an object * - * @throws IllegalArgumentException - * if inVariant = null or if inVariant is a Varint - * @param objectToBeWrapped A object that is to be referenced by this variant. - * If objectToBeWrapped is already of type Variant, then it is used. - * If objectToBeWrapped is not Variant then new Variant(objectToBeWrapped) - * is called and the result is passed into the com layer + * @param in */ - public void putVariant(Object objectToBeWrapped) { - if (objectToBeWrapped == null) { - throw new IllegalArgumentException("Cannot put null in as a variant"); - } else if (objectToBeWrapped instanceof Variant){ - throw new IllegalArgumentException("Cannot putVariant() only accepts non jacob objects."); + public Variant(byte in) { + this(new Byte(in)); + } + + /** + * Constructor that accepts a primitive rather than an object + * + * @param in + */ + public Variant(double in) { + this(new Double(in)); + } + + /** + * Constructor that accepts a primitive rather than an object + * + * @param in + */ + public Variant(float in) { + this(new Float(in)); + } + + /** + * Constructor that accepts a primitive rather than an object + * + * @param in + */ + public Variant(int in) { + this(new Integer(in)); + }; + + /** + * Constructor that accepts a primitive rather than an object + * + * @param in + */ + public Variant(long in) { + this(new Long(in)); + } + + /** + * Convenience constructor that calls the main one with a byRef value of + * false + * + * @param in + * object to be made into variant + */ + public Variant(Object in) { + this(in, false); + } + + /** + * Constructor that accepts the data object and information about whether + * this is by reference or not. It calls the JavaVariantConverter to + * actually push the data into the newly created Variant. + * + * @param pValueObject + * The value object that will pushed down into windows memory. A + * null object sets this to "empty" + * @param fByRef + */ + public Variant(Object pValueObject, boolean fByRef) { + init(); + VariantUtilities.populateVariant(this, pValueObject, fByRef); + } + + /** + * Constructor that accepts a primitive rather than an object + * + * @param in + */ + public Variant(short in) { + this(new Short(in)); + } + + /** + * Cover for native method so we can cover it. + *

+ * This cannot convert an object to a byRef. It can convert from byref to + * not byref + * + * @param in + * type to convert this variant too + * @return Variant returns this same object so folks can change when + * replacing calls toXXX() with changeType().getXXX() + */ + public Variant changeType(short in) { + changeVariantType(in); + return this; + } + + /** + * Converts variant to the passed in type by converting the underlying + * windows variant structure. private so folks use public java method + * + * @param in + * the desired resulting type + */ + private native void changeVariantType(short in); + + /** + * this returns null + * + * @return ?? comment says null? + */ + public native Object clone(); + + /** + * @deprecated No longer used + * @return null ! + */ + @Deprecated + public native Variant cloneIndirect(); + + /* + * (non-Javadoc) + * + * @see java.lang.Object#finalize() + */ + protected void finalize() { + safeRelease(); + } + + /** + * + * @return returns the value as a boolean, throws an exception if its not. + * @throws IllegalStateException + * if variant is not of the requested type + */ + public boolean getBoolean() { + if (this.getvt() == VariantBoolean) { + return getVariantBoolean(); } else { - Variant inVariant = new Variant(objectToBeWrapped); - putVariantVariant(inVariant); - // This could be done in Variant.cpp - if (JacobObject.isDebugEnabled()){ - JacobObject.debug("Zeroing out enclosed Variant's ref to windows memory"); - } - inVariant.m_pVariant = 0; + throw new IllegalStateException( + "getBoolean() only legal on Variants of type VariantBoolean, not " + + this.getvt()); } } /** - * All VariantVariant type variants are BYREF. - * - * Set the content of this variant to a string (VT_VARIANT|VT_BYREF). - * - * Added 1.12 pre 6 - VT_VARIANT support is at an alpha level - * @param in variant to be wrapped + * public cover for native method * + * @return the boolean from a booleanRef + * @throws IllegalStateException + * if variant is not of the requested type */ - private native void putVariantVariant(Variant in); + public boolean getBooleanRef() { + if ((this.getvt() & VariantBoolean) == VariantBoolean + && (this.getvt() & VariantByref) == VariantByref) { + return getVariantBooleanRef(); + } else { + throw new IllegalStateException( + "getBooleanRef() only legal on byRef Variants of type VariantBoolean, not " + + this.getvt()); + } + } /** - * Used to get the value from a windows type of VT_VARIANT - * or a jacob Variant type of VariantVariant. - * Added 1.12 pre 6 - VT_VARIANT support is at an alpha level - * @return Object a java Object that represents the content of the enclosed Variant + * + * @return returns the value as a boolean, throws an exception if its not. + * @throws IllegalStateException + * if variant is not of the requested type + */ + public byte getByte() { + if (this.getvt() == VariantByte) { + return getVariantByte(); + } else { + throw new IllegalStateException( + "getByte() only legal on Variants of type VariantByte, not " + + this.getvt()); + } + } + + /** + * public cover for native method + * + * @return the byte from a booleanRef + * @throws IllegalStateException + * if variant is not of the requested type + */ + public byte getByteRef() { + if ((this.getvt() & VariantByte) == VariantByte + && (this.getvt() & VariantByref) == VariantByref) { + return getVariantByteRef(); + } else { + throw new IllegalStateException( + "getByteRef() only legal on byRef Variants of type VariantByte, not " + + this.getvt()); + } + } + + /** + * MS Currency objects are 64 bit fixed point numbers with 15 digits to the + * left and 4 to the right of the decimal place. + * + * @return returns the currency value as a long, throws exception if not a + * currency type.. + * @throws IllegalStateException + * if variant is not of the requested type + */ + public Currency getCurrency() { + if (this.getvt() == VariantCurrency) { + return new Currency(getVariantCurrency()); + } else { + throw new IllegalStateException( + "getCurrency() only legal on Variants of type VariantCurrency, not " + + this.getvt()); + } + } + + /** + * MS Currency objects are 64 bit fixed point numbers with 15 digits to the + * left and 4 to the right of the decimal place. + * + * @return returns the currency value as a long, throws exception if not a + * currency type + * @throws IllegalStateException + * if variant is not of the requested type + */ + public Currency getCurrencyRef() { + if ((this.getvt() & VariantCurrency) == VariantCurrency + && (this.getvt() & VariantByref) == VariantByref) { + return new Currency(getVariantCurrencyRef()); + } else { + throw new IllegalStateException( + "getCurrencyRef() only legal on byRef Variants of type VariantCurrency, not " + + this.getvt()); + } + } + + /** + * @return double return the date (as a double) value held in this variant + * (fails on other types?) + * @throws IllegalStateException + * if variant is not of the requested type + */ + public double getDate() { + if (this.getvt() == VariantDate) { + return getVariantDate(); + } else { + throw new IllegalStateException( + "getDate() only legal on Variants of type VariantDate, not " + + this.getvt()); + } + } + + /** + * + * @return returns the date value as a double, throws exception if not a + * date type + * @throws IllegalStateException + * if variant is not of the requested type + */ + public double getDateRef() { + if ((this.getvt() & VariantDate) == VariantDate + && (this.getvt() & VariantByref) == VariantByref) { + return getVariantDateRef(); + } else { + throw new IllegalStateException( + "getDateRef() only legal on byRef Variants of type VariantDate, not " + + this.getvt()); + } + } + + /** + * return the BigDecimal value held in this variant (fails on other types) + * + * @return BigDecimal + * @throws IllegalStateException + * if variant is not of the requested type + */ + public BigDecimal getDecimal() { + if (this.getvt() == VariantDecimal) { + return (BigDecimal) (getVariantDec()); + } else { + throw new IllegalStateException( + "getDecimal() only legal on Variants of type VariantDecimal, not " + + this.getvt()); + } + } + + /** + * return the BigDecimal value held in this variant (fails on other types) + * + * @return BigDecimal + * @throws IllegalStateException + * if variant is not of the requested type + */ + public BigDecimal getDecimalRef() { + if ((this.getvt() & VariantDecimal) == VariantDecimal + && (this.getvt() & VariantByref) == VariantByref) { + return (BigDecimal) (getVariantDecRef()); + } else { + throw new IllegalStateException( + "getDecimalRef() only legal on byRef Variants of type VariantDecimal, not " + + this.getvt()); + } + } + + /** + * cover for {@link #toDispatch()} This method now matches other getXXX() + * methods. It throws an IllegalStateException if the object is not of type + * VariantDispatch + * + * @return this object as a dispatch + * @throws IllegalStateException + * if wrong variant type + */ + public Dispatch getDispatch() { + if ((this.getvt() & VariantDispatch) == VariantDispatch) { + return toDispatch(); + } else { + throw new IllegalStateException( + "getDispatch() only legal on Variants of type VariantDispatch, not " + + this.getvt()); + } + } + + /** + * Dispatch and dispatchRef are treated the same This is just a cover for + * toDispatch() with a flag check + * + * @return the results of toDispatch() + * @throws IllegalStateException + * if variant is not of the requested type + */ + public Dispatch getDispatchRef() { + if ((this.getvt() & VariantDispatch) == VariantDispatch + && (this.getvt() & VariantByref) == VariantByref) { + return toDispatch(); + } else { + throw new IllegalStateException( + "getDispatchRef() only legal on byRef Variants of type VariantDispatch, not " + + this.getvt()); + } + } + + /** + * @return double return the double value held in this variant (fails on + * other types?) + * @throws IllegalStateException + * if variant is not of the requested type + */ + public double getDouble() { + if (this.getvt() == VariantDouble) { + return getVariantDouble(); + } else { + throw new IllegalStateException( + "getDouble() only legal on Variants of type VariantDouble, not " + + this.getvt()); + } + } + + /** + * + * @return returns the double value, throws exception if not a Double type + * @throws IllegalStateException + * if variant is not of the requested type + */ + public double getDoubleRef() { + if ((this.getvt() & VariantDouble) == VariantDouble + && (this.getvt() & VariantByref) == VariantByref) { + return getVariantDoubleRef(); + } else { + throw new IllegalStateException( + "getDoubleRef() only legal on byRef Variants of type VariantDouble, not " + + this.getvt()); + } + } + + /** + * Pointless method that was put here so that putEmpty() has a get method. + * This would have returned null if the value was VT_EMPTY or if it wasn't + * so it would have always returned the same value. + * + * @deprecated method never did anything + */ + @Deprecated + public void getEmpty() { + } + + /** + * @return double return the error value held in this variant (fails on + * other types?) + * @throws IllegalStateException + * if variant is not of the requested type + */ + public int getError() { + if (this.getvt() == VariantError) { + return getVariantError(); + } else { + throw new IllegalStateException( + "getError() only legal on Variants of type VariantError, not " + + this.getvt()); + } + } + + /** + * + * @return returns the error value as an int, throws exception if not a + * Error type + * @throws IllegalStateException + * if variant is not of the requested type + */ + public int getErrorRef() { + if ((this.getvt() & VariantError) == VariantError + && (this.getvt() & VariantByref) == VariantByref) { + return getVariantErrorRef(); + } else { + throw new IllegalStateException( + "getErrorRef() only legal on byRef Variants of type VariantError, not " + + this.getvt()); + } + } + + /** + * @return returns the value as a float if the type is of type float + * @throws IllegalStateException + * if variant is not of the requested type + */ + public float getFloat() { + if (this.getvt() == VariantFloat) { + return getVariantFloat(); + } else { + throw new IllegalStateException( + "getFloat() only legal on Variants of type VariantFloat, not " + + this.getvt()); + } + } + + /** + * + * @return returns the float value, throws exception if not a Float type + * @throws IllegalStateException + * if variant is not of the requested type + */ + public float getFloatRef() { + if ((this.getvt() & VariantFloat) == VariantFloat + && (this.getvt() & VariantByref) == VariantByref) { + return getVariantFloatRef(); + } else { + throw new IllegalStateException( + "getFloatRef() only legal on byRef Variants of type VariantFloat, not " + + this.getvt()); + } + } + + /** + * return the int value held in this variant if it is an int or a short. + * Throws for other types. + * + * @return int contents of the windows memory + * @throws IllegalStateException + * if variant is not of the requested type + */ + public int getInt() { + if (this.getvt() == VariantInt) { + return getVariantInt(); + } else if (this.getvt() == VariantShort) { + return getVariantShort(); + } else { + throw new IllegalStateException( + "getInt() only legal on Variants of type VariantInt, not " + + this.getvt()); + } + } + + /** + * get the content of this variant as an int + * + * @return int + * @throws IllegalStateException + * if variant is not of the requested type + */ + public int getIntRef() { + if ((this.getvt() & VariantInt) == VariantInt + && (this.getvt() & VariantByref) == VariantByref) { + return getVariantIntRef(); + } else { + throw new IllegalStateException( + "getIntRef() only legal on byRef Variants of type VariantInt, not " + + this.getvt()); + } + } + + /** + * returns the windows time contained in this Variant to a Java Date. should + * return null if this is not a date Variant SF 959382 + * + * @return java.util.Date returns the date if this is a VariantDate != 0, + * null if it is a VariantDate == 0 and throws an + * IllegalStateException if this isn't a date. + * @throws IllegalStateException + * if variant is not of the requested type + */ + public Date getJavaDate() { + Date returnDate = null; + if (getvt() == VariantDate) { + double windowsDate = getDate(); + if (windowsDate != 0) { + returnDate = DateUtilities.convertWindowsTimeToDate(getDate()); + } + } else { + throw new IllegalStateException( + "getJavaDate() only legal on Variants of type VariantDate, not " + + this.getvt()); + } + return returnDate; + } + + /** + * returns the windows time contained in this Variant to a Java Date should + * return null if this is not a date reference Variant SF 959382 + * + * @return java.util.Date + */ + public Date getJavaDateRef() { + double windowsDate = getDateRef(); + if (windowsDate == 0) { + return null; + } else { + return DateUtilities.convertWindowsTimeToDate(windowsDate); + } + } + + /** + * 64 bit Longs only available on x64. 64 bit long support added 1.14 + * + * @return returns the value as a long, throws exception if not a Long + * type.. + * @throws IllegalStateException + * if variant is not of the requested type + */ + public long getLong() { + if (this.getvt() == VariantLongInt) { + return getVariantLong(); + } else { + throw new IllegalStateException( + "getLong() only legal on Variants of type VariantLongInt, not " + + this.getvt()); + } + } + + /** + * 64 bit Longs only available on x64. 64 bit long support added 1.14 + * + * @return returns the value as a long, throws exception if not a long type + * @throws IllegalStateException + * if variant is not of the requested type + */ + public long getLongRef() { + if ((this.getvt() & VariantLongInt) == VariantLongInt + && (this.getvt() & VariantByref) == VariantByref) { + return getVariantLongRef(); + } else { + throw new IllegalStateException( + "getLongRef() only legal on byRef Variants of type VariantLongInt, not " + + this.getvt()); + } + } + + /** + * This method would have returned null if the type was VT_NULL. But because + * we return null if the data is not of the right type, this method should + * have always returned null + * + * @deprecated method never did anything + */ + @Deprecated + public void getNull() { + } + + /** + * return the int value held in this variant (fails on other types?) + * + * @return int + * @throws IllegalStateException + * if variant is not of the requested type + */ + public short getShort() { + if (this.getvt() == VariantShort) { + return getVariantShort(); + } else { + throw new IllegalStateException( + "getShort() only legal on Variants of type VariantShort, not " + + this.getvt()); + } + } + + /** + * get the content of this variant as an int + * + * @return int + * @throws IllegalStateException + * if variant is not of the requested type + */ + public short getShortRef() { + if ((this.getvt() & VariantShort) == VariantShort + && (this.getvt() & VariantByref) == VariantByref) { + return getVariantShortRef(); + } else { + throw new IllegalStateException( + "getShortRef() only legal on byRef Variants of type VariantShort, not " + + this.getvt()); + } + } + + /** + * + * @return string contents of the variant. + * @throws IllegalStateException + * if this variant is not of type String + */ + public String getString() { + if (getvt() == Variant.VariantString) { + return getVariantString(); + } else { + throw new IllegalStateException( + "getString() only legal on Variants of type VariantString, not " + + this.getvt()); + } + } + + /** + * gets the content of the variant as a string ref + * + * @return String retrieved from the COM area. + * @throws IllegalStateException + * if variant is not of the requested type + */ + public String getStringRef() { + if ((this.getvt() & VariantString) == VariantString + && (this.getvt() & VariantByref) == VariantByref) { + return getVariantStringRef(); + } else { + throw new IllegalStateException( + "getStringRef() only legal on byRef Variants of type VariantString, not " + + this.getvt()); + } + } + + /** + * Used to get the value from a windows type of VT_VARIANT or a jacob + * Variant type of VariantVariant. Added 1.12 pre 6 - VT_VARIANT support is + * at an alpha level + * + * @return Object a java Object that represents the content of the enclosed + * Variant */ public Object getVariant() { if ((this.getvt() & VariantVariant) == VariantVariant && (this.getvt() & VariantByref) == VariantByref) { - if (JacobObject.isDebugEnabled()){ + if (JacobObject.isDebugEnabled()) { JacobObject.debug("About to call getVariantVariant()"); } Variant enclosedVariant = new Variant(); int enclosedVariantMemory = getVariantVariant(); enclosedVariant.m_pVariant = enclosedVariantMemory; - Object enclosedVariantAsJava = enclosedVariant.toJavaObject(); + Object enclosedVariantAsJava = enclosedVariant.toJavaObject(); // zero out the reference to the underlying windows memory so that - // it is still only owned in one place by one java object + // it is still only owned in one place by one java object // (this object of type VariantVariant) - //enclosedVariant.putEmpty(); // don't know if this would have had side effects - if (JacobObject.isDebugEnabled()){ - JacobObject.debug("Zeroing out enclosed Variant's ref to windows memory"); + // enclosedVariant.putEmpty(); // don't know if this would have had + // side effects + if (JacobObject.isDebugEnabled()) { + JacobObject + .debug("Zeroing out enclosed Variant's ref to windows memory"); } enclosedVariant.m_pVariant = 0; return enclosedVariantAsJava; @@ -477,1506 +842,1370 @@ public class Variant extends JacobObject { } /** - * Returns the variant type via a native method call. - * Added 1.12 pre 6 - VT_VARIANT support is at an alpha level + * @deprecated superseded by SafeArray + * @return never returns anything + * @throws com.jacob.com.NotImplementedException + */ + @Deprecated + public Variant[] getVariantArray() { + throw new NotImplementedException("Not implemented"); + } + + /** + * @return the Variant Array that represents the data in the Variant + * @deprecated superseded by SafeArray + * @throws com.jacob.com.NotImplementedException + */ + @Deprecated + public Variant[] getVariantArrayRef() { + throw new NotImplementedException("Not implemented"); + } + + /** + * + * @return the value in this Variant as a boolean, null if not a boolean + */ + private native boolean getVariantBoolean(); + + private native boolean getVariantBooleanRef(); + + /** + * @return the value in this Variant as a byte, null if not a byte + */ + private native byte getVariantByte(); + + /** + * @return the value in this Variant as a byte, null if not a byte + */ + private native byte getVariantByteRef(); + + /** + * @return the value in this Variant as a long, null if not a long + */ + private native long getVariantCurrency(); + + /** + * @return the value in this Variant as a long, null if not a long + */ + private native long getVariantCurrencyRef(); + + /** + * @return double return the date (as a double) value held in this variant + * (fails on other types?) + */ + private native double getVariantDate(); + + /** + * get the content of this variant as a double representing a date + * + * @return double + */ + private native double getVariantDateRef(); + + /** + * @return the value in this Variant as a decimal, null if not a decimal + */ + private native Object getVariantDec(); + + /** + * @return the value in this Variant (byref) as a decimal, null if not a + * decimal + */ + private native Object getVariantDecRef(); + + /** + * @return double get the content of this variant as a double + */ + private native double getVariantDouble(); + + /** + * @return double get the content of this variant as a double + */ + private native double getVariantDoubleRef(); + + private native int getVariantError(); + + private native int getVariantErrorRef(); + + /** + * @return returns the value as a float if the type is of type float + */ + private native float getVariantFloat(); + + /** + * @return returns the value as a float if the type is of type float + */ + private native float getVariantFloatRef(); + + /** + * @return the int value held in this variant (fails on other types?) + */ + private native int getVariantInt(); + + /** + * @return the int value held in this variant (fails on other types?) + */ + private native int getVariantIntRef(); + + /** + * @return the value in this Variant as a long, null if not a long + */ + private native long getVariantLong(); + + /** + * @return the value in this Variant as a long, null if not a long + */ + private native long getVariantLongRef(); + + /** + * get the content of this variant as a short + * + * @return short + */ + private native short getVariantShort(); + + /** + * @return short the content of this variant as a short + */ + private native short getVariantShortRef(); + + /** + * Native method that actually extracts a string value from the variant + * + * @return + */ + private native String getVariantString(); + + /** + * @return String the content of this variant as a string + */ + private native String getVariantStringRef(); + + /** + * Returns the variant type via a native method call + * + * @return short one of the VT_xx types + */ + private native short getVariantType(); + + /** + * Returns the variant type via a native method call. Added 1.12 pre 6 - + * VT_VARIANT support is at an alpha level + * * @return Variant one of the VT_Variant types */ private native int getVariantVariant(); - - /** - * get the content of this variant as a short - * @return short - */ - private native short getVariantShortRef(); - /** - * get the content of this variant as an int - * @return int - * @throws IllegalStateException if variant is not of the requested type - */ - public short getShortRef(){ - if ((this.getvt() & VariantShort) == VariantShort && - (this.getvt() & VariantByref) == VariantByref) { - return getVariantShortRef(); - } else { - throw new IllegalStateException( - "getShortRef() only legal on byRef Variants of type VariantShort, not "+this.getvt()); - } - } - - /** - * get the content of this variant as an int - * @return int - */ - private native int getVariantIntRef(); - - /** - * get the content of this variant as an int - * @return int - * @throws IllegalStateException if variant is not of the requested type - */ - public int getIntRef(){ - if ((this.getvt() & VariantInt) == VariantInt && - (this.getvt() & VariantByref) == VariantByref) { - return getVariantIntRef(); - } else { - throw new IllegalStateException( - "getIntRef() only legal on byRef Variants of type VariantInt, not "+this.getvt()); - } - } - - /** - * set the content of this variant to a short (VT_I2) - * @param in - */ - private native void putVariantShort(short in); - - /** - * set the content of this variant to a short (VT_I2) - * @param in - */ - public void putShort(short in){ - // verify we aren't released - getvt(); - putVariantShort(in); - } - /** - * get the content of this variant as a short - * @return short - */ - private native short getVariantShort(); - - /** - * return the int value held in this variant (fails on other types?) - * @return int - * @throws IllegalStateException if variant is not of the requested type - */ - public short getShort(){ - if (this.getvt() == VariantShort){ - return getVariantShort(); - } else { - throw new IllegalStateException( - "getShort() only legal on Variants of type VariantShort, not "+this.getvt()); - } - } - - - /** - * get the content of this variant as a double - * @return double - */ - private native double getVariantDoubleRef(); - - /** - * - * @return returns the double value, throws exception if not a Double type - * @throws IllegalStateException if variant is not of the requested type - */ - public double getDoubleRef(){ - if ((this.getvt() & VariantDouble) == VariantDouble && - (this.getvt() & VariantByref) == VariantByref) { - return getVariantDoubleRef(); - } else { - throw new IllegalStateException( - "getDoubleRef() only legal on byRef Variants of type VariantDouble, not "+this.getvt()); - } - } - - - /** - * get the content of this variant as a double representing a date - * @return double - */ - private native double getVariantDateRef(); - - /** - * - * @return returns the date value as a double, throws exception if not a date type - * @throws IllegalStateException if variant is not of the requested type - */ - public double getDateRef(){ - if ((this.getvt() & VariantDate) == VariantDate && - (this.getvt() & VariantByref) == VariantByref) { - return getVariantDateRef(); - } else { - throw new IllegalStateException( - "getDateRef() only legal on byRef Variants of type VariantDate, not "+this.getvt()); - } - } - - /** - * returns the windows time contained in this Variant to a Java Date - * should return null if this is not a date reference Variant - * SF 959382 - * @return java.util.Date - */ - public Date getJavaDateRef(){ - double windowsDate = getDateRef(); - if (windowsDate == 0){ - return null; - } else { - return DateUtilities.convertWindowsTimeToDate(windowsDate); - } - } - - /** - * get the content of this variant as a string - * @return String - */ - private native String getVariantStringRef(); - - /** - * gets the content of the veriant as a string ref - * @return String retrieved from the COM area. - * @throws IllegalStateException if variant is not of the requested type - */ - public String getStringRef(){ - if ((this.getvt() & VariantString) == VariantString && - (this.getvt() & VariantByref) == VariantByref) { - return getVariantStringRef(); - } else { - throw new IllegalStateException( - "getStringRef() only legal on byRef Variants of type VariantString, not "+this.getvt()); - } - } - - - /** - * @deprecated superceded by SafeArray - * @return never returns anything - * @throws com.jacob.com.NotImplementedException - */ - public Object toCharArray() { - throw new NotImplementedException("Not implemented"); - } - - /** - * Clear the content of this variant - */ - public native void VariantClear(); - - /** - * @return the content of this variant as a Dispatch object (after possible conversion) - */ - public Dispatch toDispatch(){ - // now make the native call - return toVariantDispatch(); - } - - /** - * native method used by toDispatch() - * @return - */ - private native Dispatch toVariantDispatch(); - - /** - * this returns null - * @return ?? comment says null? - */ - public native Object clone(); - - /** - * This method now correctly implements java toString() semantics - * Attempts to return the content of this variant as a string - *

    - *
  • "not initialized" if not initialized - *
  • "null" if VariantEmpty, - *
  • "null" if VariantError - *
  • "null" if VariantNull - *
  • the value if we know how to describe one of that type - *
  • three question marks if can't convert - * @return String value conversion, - * @throws IllegalStateException if there is no underlying windows data structure - */ - public String toString(){ - try { - // see if we are in a legal state - getvt(); - } catch (IllegalStateException ise){ - return ""; - } - if (getvt() == VariantEmpty || getvt() == VariantError || getvt() == VariantNull){ - return "null"; - } - if (getvt() == VariantString){ - return getString(); - } - try { - Object foo = toJavaObject(); - // rely on java objects to do the right thing - return foo.toString(); - } catch (NotImplementedException nie){ - // some types do not generate a good description yet - return "Description not available for type: "+getvt(); - } - } - - /** - * return the int value held in this variant (fails on other types?) - * @return int - */ - private native int getVariantInt(); - - /** - * return the int value held in this variant if it is an int or a short. - * Throws for other types. - * @return int contents of the windows membory - * @throws IllegalStateException if variant is not of the requested type - */ - public int getInt(){ - if (this.getvt() == VariantInt){ - return getVariantInt(); - } else if (this.getvt() == VariantShort){ - return (int)getVariantShort(); - } else { - throw new IllegalStateException( - "getInt() only legal on Variants of type VariantInt, not "+this.getvt()); - } - } - - /** - * @return double return the date (as a double) value held in this variant (fails on other types?) - */ - private native double getVariantDate(); - - /** - * @return double return the date (as a double) value held in this variant (fails on other types?) - * @throws IllegalStateException if variant is not of the requested type - */ - public double getDate(){ - if (this.getvt() == VariantDate){ - return getVariantDate(); - } else { - throw new IllegalStateException( - "getDate() only legal on Variants of type VariantDate, not "+this.getvt()); - } - } - - - /** - * returns the windows time contained in this Variant to a Java Date. - * should return null if this is not a date Variant - * SF 959382 - * @return java.util.Date returns the date if this is a VariantDate != 0, - * null if it is a VariantDate == 0 and throws an IllegalStateException if this isn't - * a date. - * @throws IllegalStateException if variant is not of the requested type - */ - public Date getJavaDate(){ - Date returnDate = null; - if (getvt() == VariantDate){ - double windowsDate = getDate(); - if (windowsDate != 0){ - returnDate = DateUtilities.convertWindowsTimeToDate(getDate()); - } - } else { - throw new IllegalStateException( - "getJavaDate() only legal on Variants of type VariantDate, not "+this.getvt()); - } - return returnDate; - } - - /** - * set the value of this variant and set the type - * @param in - */ - private native void putVariantInt(int in); - - /** - * set the value of this variant and set the type - * @param in - */ - public void putInt(int in){ - // verify we aren't released yet - getvt(); - putVariantInt(in); - } - - - /** - * @return the value in this Variant as a decimal, null if not a decimal - */ - private native Object getVariantDec(); - - - /** - * @return the value in this Variant (byref) as a decimal, null if not a decimal - */ - private native Object getVariantDecRef(); - - - /** - * return the BigDecimal value held in this variant (fails on other types) - * @return BigDecimal - * @throws IllegalStateException if variant is not of the requested type - */ - public BigDecimal getDecimal() { - if (this.getvt() == VariantDecimal) { - return (BigDecimal) (getVariantDec()); - } else { - throw new IllegalStateException( - "getDecimal() only legal on Variants of type VariantDecimal, not " - + this.getvt()); - } - } - - /** - * return the BigDecimal value held in this variant (fails on other types) + /** + * Reports the type of the underlying Variant object * - * @return BigDecimal + * @return returns the variant type as a short, one of the Variantxxx values + * defined as statics in this class. returns VariantNull if not + * initialized * @throws IllegalStateException - * if variant is not of the requested type + * if there is no underlying windows data structure */ - public BigDecimal getDecimalRef() { - if ((this.getvt() & VariantDecimal) == VariantDecimal - && (this.getvt() & VariantByref) == VariantByref) { - return (BigDecimal) (getVariantDecRef()); + public short getvt() { + if (m_pVariant != 0) { + return getVariantType(); } else { - throw new IllegalStateException( - "getDecimalRef() only legal on byRef Variants of type VariantDecimal, not " - + this.getvt()); + throw new IllegalStateException("uninitialized Variant"); } } - /** - * private JNI method called by putDecimal - * @param signum sign - * @param scale BigDecimal's scale - * @param lo low 32 bits - * @param mid middle 32 bits - * @param hi high 32 bits - */ - private native void putVariantDec(int signum, byte scale, int lo, int mid, int hi); - - /** - * Set the value of this variant and set the type. - * This may throw exceptions more often than the caller expects because - * most callers don't manage the scale of their BigDecimal objects. - * @param in the big decimal that will convert to the VT_DECIMAL type - * @throws IllegalArgumentException if the scale is > 28, the maximum for VT_DECIMAL - */ - public void putDecimal(BigDecimal in) { + /** + * initializes the COM Variant and puts its reference in this instance + */ + protected native void init(); + + /** + * + * @return returns true if the variant is considered null + * @throws IllegalStateException + * if there is no underlying windows memory + */ + public boolean isNull() { + getvt(); + return isVariantConsideredNull(); + } + + /** + * is the variant null or empty or error or null dispatch + * + * @return true if it is null or false if not + */ + private native boolean isVariantConsideredNull(); + + /** + * sets the type to VT_ERROR and the error message to DISP_E_PARAMNOTFOIUND + * + * @deprecated replaced by putNoParam() + */ + @Deprecated + public void noParam() { + putNoParam(); + } + + /** + * returns true if the passed in Variant is a constant that should not be + * freed + * + * @param pVariant + * @return boolean that is true if Variant is a type of constant, VT_FALSE, + * VT_TRUE, VT_MISSING, DEFAULT + */ + protected boolean objectIsAConstant(Variant pVariant) { + if (pVariant == VT_FALSE || pVariant == VT_TRUE + || pVariant == VT_MISSING || pVariant == DEFAULT) { + return true; + } else { + return false; + } + + } + + /** + * puts a boolean into the variant and sets it's type + * + * @param in + * the new value + */ + public void putBoolean(boolean in) { // verify we aren't released yet getvt(); - if (in.scale() > 28) { - // should this really cast to a string and call putStringRef()? + putVariantBoolean(in); + } + + /** + * pushes a boolean into the variant by ref and sets the type of the variant + * to boolean + * + * @param in + */ + public void putBooleanRef(boolean in) { + // verify we aren't released yet + getvt(); + putVariantBooleanRef(in); + } + + /** + * pushes a byte into the varaint and sets the type + * + * @param in + */ + public void putByte(byte in) { + // verify we aren't released yet + getvt(); + putVariantByte(in); + }; + + /** + * @deprecated superseded by SafeArray + * @param in + * doesn't matter because this method does nothing + * @throws com.jacob.com.NotImplementedException + */ + @Deprecated + public void putByteArray(Object in) { + throw new NotImplementedException("Not implemented"); + } + + /** + * pushes a byte into the variant by ref and sets the type + * + * @param in + */ + public void putByteRef(byte in) { + // verify we aren't released yet + getvt(); + putVariantByteRef(in); + } + + /** + * @param in + * the object that would be wrapped by the Variant if this method + * was implemented + * @deprecated superseded by SafeArray + * @throws com.jacob.com.NotImplementedException + */ + @Deprecated + public void putCharArray(Object in) { + throw new NotImplementedException("Not implemented"); + } + + /** + * Puts a value in as a currency and sets the variant type. MS Currency + * objects are 64 bit fixed point numbers with 15 digits to the left and 4 + * to the right of the decimal place. + * + * @param in + * the long that will be put into the 64 bit currency object. + */ + public void putCurrency(Currency in) { + // verify we aren't released yet + getvt(); + putVariantCurrency(in.longValue()); + } + + /** + * Pushes a long into the variant as currency and sets the type. MS Currency + * objects are 64 bit fixed point numbers with 15 digits to the left and 4 + * to the right of the decimal place. + * + * @param in + * the long that will be put into the 64 bit currency object + */ + public void putCurrencyRef(Currency in) { + // verify we aren't released yet + getvt(); + putVariantCurrencyRef(in.longValue()); + } + + /** + * converts a java date to a windows time and calls putDate(double) SF + * 959382 + * + * @param inDate + * a Java date to be converted + * @throws IllegalArgumentException + * if inDate = null + */ + public void putDate(Date inDate) { + if (inDate == null) { throw new IllegalArgumentException( - "VT_DECIMAL only supports a scale of 28 and the passed" - + " in value has a scale of " + in.scale()); + "Cannot put null in as windows date"); + // do nothing } else { - byte scale = (byte) in.scale(); - BigInteger unscaled = in.unscaledValue(); - BigInteger shifted = unscaled.shiftRight(32); - putVariantDec( in.signum(), scale, unscaled.intValue(), shifted - .intValue(), shifted.shiftRight(32).intValue()); + putDate(DateUtilities.convertDateToWindowsTime(inDate)); } } - /** + /** + * puts a windows date double into the variant and sets the type + * + * @param in + */ + public void putDate(double in) { + // verify we aren't released yet + getvt(); + putVariantDate(in); + } + + /** + * converts a java date to a windows time and calls putDateRef(double) SF + * 959382 + * + * @param inDate + * a Java date to be converted + * @throws IllegalArgumentException + * if inDate = null + */ + public void putDateRef(Date inDate) { + if (inDate == null) { + throw new IllegalArgumentException( + "Cannot put null in as windows date"); + // do nothing + } else { + putDateRef(DateUtilities.convertDateToWindowsTime(inDate)); + } + } + + /** + * set the content of this variant to a date (VT_DATE|VT_BYREF) + * + * @param in + */ + public void putDateRef(double in) { + // verify we aren't released + getvt(); + putVariantDateRef(in); + } + + /** + * This actual does all the validating and massaging of the BigDecimalValues + * when converting them to MS Decimal types + * + * @param in + * number to be made into VT_DECIMAL + * @param byRef + * store by reference or not + * @param roundingBehavior + * one of the BigDecimal ROUND_xxx methods. Any method other than + * ROUND_UNECESSARY means that the value will be rounded to fit + */ + private void putDecimal(BigDecimal in, boolean byRef) { + // verify we aren't released + getvt(); + // first validate the min and max + VariantUtilities.validateDecimalMinMax(in); + BigInteger allWordBigInt; + allWordBigInt = in.unscaledValue(); + // Assume any required rounding has been done. + VariantUtilities.validateDecimalScaleAndBits(in); + // finally we can do what we actually came here to do + int sign = in.signum(); + // VT_DECIMAL always has positive value with just the sign + // flipped + if (in.signum() < 0) { + in = in.negate(); + } + // ugh, reusing allWordBigInt but now should always be positive + // and any round is applied + allWordBigInt = in.unscaledValue(); + byte scale = (byte) in.scale(); + int lowWord = allWordBigInt.intValue(); + BigInteger middleWordBigInt = allWordBigInt.shiftRight(32); + int middleWord = middleWordBigInt.intValue(); + BigInteger highWordBigInt = allWordBigInt.shiftRight(64); + int highWord = highWordBigInt.intValue(); + if (byRef) { + putVariantDecRef(sign, scale, lowWord, middleWord, highWord); + } else { + putVariantDec(sign, scale, lowWord, middleWord, highWord); + } + } + + /** + * EXPERIMENTAL 1.14 feature to support rounded decimals. + *

    + * Set the value of this variant and set the type. This may throw exceptions + * more often than the caller expects because most callers don't manage the + * scale of their BigDecimal objects. + *

    + * This default set method throws exceptions if precision or size is out of + * bounds + *

    + * There are 12 bytes available for the integer number. + *

    + * There is 1 byte for the scale. + * + * @param in + * the BigDecimal that will be converted to VT_DECIMAL + * @throws IllegalArgumentException + * if the scale is > 28, the maximum for VT_DECIMAL or if there + * are more than 12 bytes worth the digits + */ + public void putDecimal(BigDecimal in) { + putDecimal(in, false); + } + + /** + * Set the value of this variant and set the type. This may throw exceptions + * more often than the caller expects because most callers don't manage the + * scale of their BigDecimal objects. + *

    + * This default set method throws exceptions if precision or size is out of + * bounds + *

    + * There are 12 bytes available for the integer number. + *

    + * There is 1 byte for the scale. + * + * @param in + * the BigDecimal that will be converted to VT_DECIMAL + * @throws IllegalArgumentException + * if the scale is > 28, the maximum for VT_DECIMAL or if there + * are more than 12 bytes worth the digits + */ + public void putDecimalRef(BigDecimal in) { + putDecimal(in, true); + } + + /** + * This acts a cover for putVariant Dispatch. + * + * @param in + * the Dispatch we're putting down in the COM variant space. + */ + public void putDispatch(Dispatch in) { + putVariantDispatch(in); + } + + /** + * Dispatch and dispatchRef are treated the same This is a cover for + * putVariantDispatch(). putDispatch and putDispatchRef are treated the same + * because no one has written the COM code for putDispatchRef. + * + * @param in + * the Dispatch we're putting down in the COM variant space. + */ + public void putDispatchRef(Dispatch in) { + putVariantDispatch(in); + } + + /** + * wraps this Variant around the passed in double. + * + * @param in + */ + public void putDouble(double in) { + // verify we aren't released yet + getvt(); + putVariantDouble(in); + } + + /** + * set the content of this variant to a double (VT_R8|VT_BYREF) + * + * @param in + */ + public void putDoubleRef(double in) { + // verify we aren't released + getvt(); + putVariantDoubleRef(in); + } + + /** + * sets the type to VariantEmpty + * + */ + public void putEmpty() { + // verify we aren't released yet + getvt(); + putVariantEmpty(); + } + + /** + * puts an error code (I think) into the variant and sets the type + * + * @param in + */ + public void putError(int in) { + // verify we aren't released yet + getvt(); + putVariantError(in); + } + + /** + * pushes an error code into the variant by ref and sets the type + * + * @param in + */ + public void putErrorRef(int in) { + // verify we aren't released yet + getvt(); + putVariantErrorRef(in); + } + + /** + * fills the Variant with a float and sets the type to float + * + * @param in + */ + public void putFloat(float in) { + // verify we haven't been released yet + getvt(); + putVariantFloat(in); + } + + /** + * pushes a float into the variant and sets the type + * + * @param in + */ + public void putFloatRef(float in) { + // verify we aren't released yet + getvt(); + putVariantFloatRef(in); + } + + /** + * set the value of this variant and set the type + * + * @param in + */ + public void putInt(int in) { + // verify we aren't released yet + getvt(); + putVariantInt(in); + } + + /** + * set the content of this variant to an int (VT_I4|VT_BYREF) + * + * @param in + */ + public void putIntRef(int in) { + // verify we aren't released + getvt(); + putVariantIntRef(in); + } + + /** + * Puts a 64 bit Java Long into a 64 bit Variant Long. Only works on x64 + * systems otherwise throws an error. 64 bit long support added 1.14 + * + * @param in + * the long that will be put into the 64 bit Long object. + */ + public void putLong(long in) { + // verify we aren't released yet + getvt(); + putVariantLong(in); + } + + /** + * Puts a 64 bit Java Long into a 64 bit Variant Long. Only works on x64 + * systems otherwise throws an error. 64 bit long support added 1.14 + * + * @param in + * the long that will be put into the 64 bit Long object. + */ + public void putLongRef(long in) { + // verify we aren't released yet + getvt(); + putVariantLongRef(in); + } + + /** + * sets the type to VT_ERROR and the error message to DISP_E_PARAMNOTFOIUND + */ + public void putNoParam() { + // verify we aren't released yet + getvt(); + putVariantNoParam(); + } + + /** + * Sets the type to VariantDispatch and sets the value to null Equivalent to + * VB's nothing + */ + public void putNothing() { + // verify we aren't released yet + getvt(); + putVariantNothing(); + } + + /** + * Set this Variant's type to VT_NULL (the VB equivalent of NULL) + */ + public void putNull() { + // verify we aren't released yet + getvt(); + putVariantNull(); + } + + /** + * Puts an object into the Variant -- converts to Dispatch. Acts as a cover + * for putVariantDispatch(); This primarily exists to support jacobgen. This + * should be deprecated. + * + * @param in + * the object we are putting into the Variant, assumes a + * @see Variant#putDispatch(Dispatch) + * @deprecated should use putDispatch() + */ + @Deprecated + public void putObject(Object in) { + // this should verify in instanceof Dispatch + putVariantDispatch(in); + } + + /** + * Just a cover for putObject(). We shouldn't accept any old random object. + * This has been left in to support jacobgen. This should be deprecated. + * + * @param in + * @deprecated + */ + @Deprecated + public void putObjectRef(Object in) { + putObject(in); + } + + /** + * have no idea... + * + * @param in + */ + public void putSafeArray(SafeArray in) { + // verify we haven't been released yet + getvt(); + putVariantSafeArray(in); + } + + /** + * have no idea... + * + * @param in + */ + public void putSafeArrayRef(SafeArray in) { + // verify we haven't been released yet + getvt(); + putVariantSafeArrayRef(in); + } + + /** + * set the content of this variant to a short (VT_I2) + * + * @param in + */ + public void putShort(short in) { + // verify we aren't released + getvt(); + putVariantShort(in); + } + + /** + * set the content of this variant to a short (VT_I2|VT_BYREF) + * + * @param in + */ + public void putShortRef(short in) { + // verify we aren't released + getvt(); + putVariantShortRef(in); + } + + /** + * put a string into the variant and set its type + * + * @param in + */ + public void putString(String in) { + // verify we aren't released yet + getvt(); + putVariantString(in); + } + + /** + * set the content of this variant to a string (VT_BSTR|VT_BYREF) + * + * @param in + */ + public void putStringRef(String in) { + // verify we aren't released + getvt(); + putVariantStringRef(in); + } + + /** + * Puts a variant into this variant making it type VT_VARIANT. Added 1.12 + * pre 6 + * + * @param objectToBeWrapped + * A object that is to be referenced by this variant. If + * objectToBeWrapped is already of type Variant, then it is used. + * If objectToBeWrapped is not Variant then + * new Variant(objectToBeWrapped) is called and + * the result is passed into the com layer + * @throws IllegalArgumentException + * if inVariant = null or if inVariant is a Varint + */ + public void putVariant(Object objectToBeWrapped) { + if (objectToBeWrapped == null) { + throw new IllegalArgumentException( + "Cannot put null in as a variant"); + } else if (objectToBeWrapped instanceof Variant) { + throw new IllegalArgumentException( + "Cannot putVariant() only accepts non jacob objects."); + } else { + Variant inVariant = new Variant(objectToBeWrapped); + putVariantVariant(inVariant); + // This could be done in Variant.cpp + if (JacobObject.isDebugEnabled()) { + JacobObject + .debug("Zeroing out enclosed Variant's ref to windows memory"); + } + inVariant.m_pVariant = 0; + } + } + + /** + * @deprecated superseded by SafeArray + * @param in + * doesn't matter because this method does nothing + * @throws com.jacob.com.NotImplementedException + */ + @Deprecated + public void putVariantArray(Variant[] in) { + throw new NotImplementedException("Not implemented"); + } + + /** + * @param in + * the thing that would be come an array if this method was + * implemented + * @deprecated superseded by SafeArray + * @throws com.jacob.com.NotImplementedException + */ + @Deprecated + public void putVariantArrayRef(Variant[] in) { + throw new NotImplementedException("Not implemented"); + } + + /** + * puts a boolean into the variant and sets it's type + * + * @param in + * the new value + */ + private native void putVariantBoolean(boolean in); + + /** + * puts a boolean into the variant and sets it's type + * + * @param in + * the new value + */ + private native void putVariantBooleanRef(boolean in); + + /** + * puts a byte into the variant and sets it's type + * + * @param in + * the new value + */ + private native void putVariantByte(byte in); + + /** + * puts a byte into the variant and sets it's type + * + * @param in + * the new value + */ + private native void putVariantByteRef(byte in); + + /** + * puts a Currency into the variant and sets it's type + * + * @param in + * the new value + */ + private native void putVariantCurrency(long in); + + /** + * puts a Currency into the variant and sets it's type + * + * @param in + * the new value + */ + private native void putVariantCurrencyRef(long in); + + /** * set the value of this variant * * @param in */ - private native void putVariantDate(double in); - - /** - * puts a windows date double into the variant and sets the type - * @param in - */ - public void putDate(double in){ - // verify we aren't released yet - getvt(); - putVariantDate(in); - } - /** - * converts a java date to a windows time and calls putDate(double) - * SF 959382 - * @throws IllegalArgumentException if inDate = null - * @param inDate a Java date to be converted - */ - public void putDate(Date inDate){ - if (inDate == null){ - throw new IllegalArgumentException("Cannot put null in as windows date"); - // do nothing - } else { - putDate(DateUtilities.convertDateToWindowsTime(inDate)); - } - } - - /** - * attempts to return the content of this variant as a double - * (after possible conversion) - * @deprecated should be replaced by changeType() followed by getByte() - * @return byte - */ - public byte toByte(){ - changeType(Variant.VariantByte); - return getByte(); - } - - /** - * cover for {@link #toDispatch()} - * This method now matches other getXXX() methods. It throws an IllegalStateException - * if the object is not of type VariantDispatch - * @return this object as a dispatch - * @throws IllegalStateException if wrong variant type - */ - public Dispatch getDispatch() { - if ((this.getvt() & VariantDispatch) == VariantDispatch) { - return toDispatch(); - } else { - throw new IllegalStateException( - "getDispatch() only legal on Variants of type VariantDispatch, not "+this.getvt()); - } - } - - /** - * This acts a cover for - * same as @link #putObject(Object) - * - * Why isn't this typed as type Dispatch? - * @param in - */ - public void putDispatch(Dispatch in) { - putVariantDispatch(in); - } - - /** - * - * @return the value in this Variant as a boolean, null if not a boolean - */ - private native boolean getVariantBoolean(); - - /** - * - * @return returns the value as a boolean, throws an exception if its not. - * @throws IllegalStateException if variant is not of the requested type - */ - public boolean getBoolean(){ - if (this.getvt() == VariantBoolean){ - return getVariantBoolean(); - } else { - throw new IllegalStateException ( - "getBoolean() only legal on Variants of type VariantBoolean, not "+this.getvt()); - } - } - - /** - * - * @return the value in this Variant as a byte, null if not a byte - */ - private native byte getVariantByte(); - - /** - * - * @return returns the value as a boolean, throws an exception if its not. - * @throws IllegalStateException if variant is not of the requested type - */ - public byte getByte(){ - if (this.getvt() == VariantByte){ - return getVariantByte(); - } else { - throw new IllegalStateException( - "getByte() only legal on Variants of type VariantByte, not "+this.getvt()); - } - } - - /** - * puts a boolean into the variant and sets it's type - * @param in the new value - */ - private native void putVariantBoolean(boolean in); - - /** - * puts a boolean into the variant and sets it's type - * @param in the new value - */ - public void putBoolean(boolean in){ - // verify we aren't released yet - getvt(); - putVariantBoolean(in); - } - - private native void putVariantByte(byte in); - - /** - * pushes a byte into the varaint and sets the type - * @param in - */ - public void putByte(byte in){ - // verify we aren't released yet - getvt(); - putVariantByte(in); - } - - /** - * converts to an error type and returns the error - * @deprecated should use changeType() followed by getError() - * @return the error as an int (after conversion) - */ - public int toError(){ - changeType(Variant.VariantError); - return getError(); - } - - /** - * Acts a a cover for toDispatch. - * This primarily exists to support jacobgen. - * @deprecated this is a cover for toDispatch(); - * @return Object returned by toDispatch() - * @see Variant#toDispatch() instead - */ - public Object toObject() { - return toDispatch(); - } - - /** - * Pointless method that was put here so that putEmpty() has a get method. - * This would have returned null if the value was VT_EMPTY - * or if it wasn't so it would have always returned the same value. - * @deprecated method never did anything - */ - public void getEmpty() {}; - - /** - * Sets the type to VariantEmpty. No values needed - */ - private native void putVariantEmpty(); - - /** - * sets the type to VariantEmpty - * - */ - public void putEmpty(){ - // verify we aren't released yet - getvt(); - putVariantEmpty(); - } - - /** - * Sets the type to VariantDispatch and sets the value to null - * Equivalent to VB's nothing - */ - private native void putVariantNothing(); - - /** - * Sets the type to VariantDispatch and sets the value to null - * Equivalent to VB's nothing - */ - public void putNothing(){ - // verify we aren't released yet - getvt(); - putVariantNothing(); - } - - private native int getVariantError(); - - /** - * @return double return the error value held in this variant (fails on other types?) - * @throws IllegalStateException if variant is not of the requested type - */ - public int getError(){ - if (this.getvt() == VariantError){ - return getVariantError(); - } else { - throw new IllegalStateException( - "getError() only legal on Variants of type VariantError, not "+this.getvt()); - } - } - - - private native void putVariantError(int in); - - /** - * puts an error code (I think) into the variant and sets the type - * @param in - */ - public void putError(int in){ - // verify we aren't released yet - getvt(); - putVariantError(in); - } - - private native double getVariantDouble(); - - /** - * @return double return the double value held in this variant (fails on other types?) - * @throws IllegalStateException if variant is not of the requested type - */ - public double getDouble(){ - if (this.getvt() == VariantDouble){ - return getVariantDouble(); - } else { - throw new IllegalStateException( - "getDouble() only legal on Variants of type VariantDouble, not "+this.getvt()); - } - } - - - private native void putVariantCurrency(long in); - - /** - * Puts a value in as a currency and sets the variant type. - * MS Currency objects are 64 bit fixed point numbers with 15 digits to the left - * and 4 to the right of the decimal place. - * @param in the long that will be put into the 64 bit currency object. - */ - public void putCurrency(long in){ - // verify we aren't released yet - getvt(); - putVariantCurrency(in); - } - - /** - * Puts an object into the Variant -- converts to Dispatch. - * Acts as a cover for putVariantDispatch(); - * This primarily exists to support jacobgen. - * This should be deprecated. - * @see Variant#putDispatch(Dispatch) - * @deprecated should use putDispatch() - * */ - public void putObject(Object in){ - // this should verify in instanceof Dispatch - putVariantDispatch(in); } - - /** - * the JNI implementation for putDispatch() so that - * we can screen the incoming dispatches in putDispatch() before this - * is invoked - * @param in should be a dispatch object - */ - private native void putVariantDispatch(Object in); - - private native void putVariantDouble(double in); - - public void putDouble(double in){ - // verify we aren't released yet - getvt(); - putVariantDouble(in); - } - - /** - * - * @return the value in this Variant as a long, null if not a long - */ - private native long getVariantCurrency(); - - /** - * MS Currency objects are 64 bit fixed point numbers with 15 digits to the left - * and 4 to the right of the decimal place. - * @return returns the currency value as a long, throws exception if not a currency type.. - * @throws IllegalStateException if variant is not of the requested type - */ - public long getCurrency(){ - if (this.getvt() == VariantCurrency){ - return getVariantCurrency(); - } else { - throw new IllegalStateException( - "getCurrency() only legal on Variants of type VariantCurrency, not "+this.getvt()); - } - } - - private native void putVariantFloatRef(float in); - - /** - * pushes a float into the variant and sets the type - * @param in - */ - public void putFloatRef(float in){ - // verify we aren't released yet - getvt(); - putVariantFloatRef(in); - } - - private native void putVariantCurrencyRef(long in); - - /** - * Pushes a long into the variant as currency and sets the type. - * MS Currency objects are 64 bit fixed point numbers with 15 digits to the left - * and 4 to the right of the decimal place. - * @param in the long that will be put into the 64 bit currency object - */ - public void putCurrencyRef(long in){ - // verify we aren't released yet - getvt(); - putVariantCurrencyRef(in); - } - - private native void putVariantErrorRef(int in); - - /** - * pushes an error code into the variant by ref and sets the type - * @param in - */ - public void putErrorRef(int in){ - // verify we aren't released yet - getvt(); - putVariantErrorRef(in); - } - - private native void putVariantBooleanRef(boolean in); - - /** - * pushes a boolean into the variant by ref and sets the type of the variant to boolean - * @param in - */ - public void putBooleanRef(boolean in){ - // verify we aren't released yet - getvt(); - putVariantBooleanRef(in); - } - - /** - * Just a cover for putObject(). - * We shouldn't accept any old random object. - * This has been left in to support jacobgen. - * This should be deprecated. - * @param in - * @deprecated - */ - public void putObjectRef(Object in) { - putObject(in); - } - - private native void putVariantByteRef(byte in); - - /** - * pushes a byte into the variant by ref and sets the type - * @param in - */ - public void putByteRef(byte in){ - // verify we aren't released yet - getvt(); - putVariantByteRef(in); - } - /** - * Native method that actually extracts a string value from the variant - * @return - */ - private native String getVariantString(); - - /** - * - * @return string contents of the variant. - * @throws IllegalStateException if this variant is not of type String - */ - public String getString(){ - if (getvt() == Variant.VariantString){ - return getVariantString(); - } else { - throw new IllegalStateException( - "getString() only legal on Variants of type VariantString, not "+this.getvt()); - } - } - - private native void putVariantString(String in); - - /** - * put a string into the variant and set its type - * @param in - */ - public void putString(String in){ - // verify we aren't released yet - getvt(); - putVariantString(in); - } - - private native float getVariantFloatRef(); - - /** - * - * @return returns the float value, throws exception if not a Float type - * @throws IllegalStateException if variant is not of the requested type - */ - public float getFloatRef(){ - if ((this.getvt() & VariantFloat) == VariantFloat && - (this.getvt() & VariantByref) == VariantByref) { - return getVariantFloatRef(); - } else { - throw new IllegalStateException( - "getFloatRef() only legal on byRef Variants of type VariantFloat, not "+this.getvt()); - } - } - - - private native long getVariantCurrencyRef(); - - /** - * MS Currency objects are 64 bit fixed point numbers with 15 digits to the left - * and 4 to the right of the decimal place. - * @return returns the currency value as a long, throws exception if not a currency type - * @throws IllegalStateException if variant is not of the requested type - */ - public long getCurrencyRef(){ - if ((this.getvt() & VariantCurrency) == VariantCurrency && - (this.getvt() & VariantByref) == VariantByref) { - return getVariantCurrencyRef(); - } else { - throw new IllegalStateException( - "getCurrencyRef() only legal on byRef Variants of type VariantCurrency, not "+this.getvt()); - } - } - - - private native int getVariantErrorRef(); - - /** - * - * @return returns the error value as an int, throws exception if not a Error type - * @throws IllegalStateException if variant is not of the requested type - */ - public int getErrorRef(){ - if ((this.getvt() & VariantError) == VariantError && - (this.getvt() & VariantByref) == VariantByref) { - return getVariantErrorRef(); - } else { - throw new IllegalStateException( - "getErrorRef() only legal on byRef Variants of type VariantError, not "+this.getvt()); - } - } - - - private native boolean getVariantBooleanRef(); - - /** - * public cover for native method - * @return the boolean from a booleanRef - * @throws IllegalStateException if variant is not of the requested type - */ - public boolean getBooleanRef(){ - if ((this.getvt() & VariantBoolean) == VariantBoolean && - (this.getvt() & VariantByref) == VariantByref) { - return getVariantBooleanRef(); - } else { - throw new IllegalStateException( - "getBooleanRef() only legal on byRef Variants of type VariantBoolean, not "+this.getvt()); - } - } - - private native byte getVariantByteRef(); - - /** - * public cover for native method - * @return the byte from a booleanRef - * @throws IllegalStateException if variant is not of the requested type - */ - public byte getByteRef(){ - if ((this.getvt() & VariantByte) == VariantByte && - (this.getvt() & VariantByref) == VariantByref) { - return getVariantByteRef(); - } else { - throw new IllegalStateException( - "getByteRef() only legal on byRef Variants of type VariantByte, not "+this.getvt()); - } - } - - - /** - * attempts to return the contents of this variant as a float - * (after possible conversion) - * @deprecated should use changeType() and getFloat() instead - * @return float - */ - public float toFloat(){ - changeType(Variant.VariantFloat); - return getFloat(); - } - - private native SafeArray toVariantSafeArray(boolean deepCopy); - - /** - * By default toSafeArray makes a deep copy due to the fact that this - * Variant owns the embedded SafeArray and will destroy it when it gc's - * calls toSafeArray(true). - */ - public SafeArray toSafeArray() { - // verify we haven't been released yet - getvt(); - return toSafeArray(true); - } - - /** - * This lets folk turn into a safe array without a deep copy. - * Shoudl this API be public? - * @param deepCopy - * @return SafeArray constructed - */ - public SafeArray toSafeArray(boolean deepCopy){ - // verify we haven't been released yet - getvt(); - return toVariantSafeArray(deepCopy); - } - - private native void putVariantSafeArrayRef(SafeArray in); - - /** - * have no idea... - * @param in - */ - public void putSafeArrayRef(SafeArray in){ - // verify we haven't been released yet - getvt(); - putVariantSafeArrayRef(in); - } - - private native void putVariantSafeArray(SafeArray in); - - - /** - * have no idea... - * @param in - */ - public void putSafeArray(SafeArray in){ - // verify we haven't been released yet - getvt(); - putVariantSafeArray(in); - } - - /** - * sets the type to VT_ERROR and the error message to DISP_E_PARAMNOTFOIUND - * */ - private native void putVariantNoParam(); - - /** - * sets the type to VT_ERROR and the error message to DISP_E_PARAMNOTFOIUND - * */ - public void putNoParam(){ - // verify we aren't released yet - getvt(); - putVariantNoParam(); - } - - /** - * sets the type to VT_ERROR and the error message to DISP_E_PARAMNOTFOIUND - * @deprecated replaced by putNoParam() - * */ - public void noParam(){ - putNoParam(); - } - /** - * @deprecated superceded by SafeArray - * @throws com.jacob.com.NotImplementedException - */ - public void putCharArray(Object in) { - throw new NotImplementedException("Not implemented"); - } - - /** - * - * @return returns the value as a float if the type is of type float - */ - private native float getVariantFloat(); - - /** - * @return returns the value as a float if the type is of type float - * @throws IllegalStateException if variant is not of the requested type - */ - public float getFloat(){ - if (this.getvt() == VariantFloat){ - return getVariantFloat(); - } else { - throw new IllegalStateException( - "getFloat() only legal on Variants of type VariantFloat, not "+this.getvt()); - } - } - - - /** - * fills the Variant with a float and sets the type to float - * @param in - */ - private native void putVariantFloat(float in); - - /** - * fills the Variant with a float and sets the type to float - * @param in - */ - public void putFloat(float in){ - // verify we haven't been released yet - getvt(); - putVariantFloat(in); - } - - /** - * Dispatch and dispatchRef are treated the same - * This is a cover for putVariantDispatch(). - * Dispatch and dispatchRef are treated the same - * @param in - */ - public void putDispatchRef(Dispatch in) { - putVariantDispatch(in); - } - - /** - * Dispatch and dispatchRef are treated the same - * This is just a cover for toDispatch() with a flag check - * @return the results of toDispatch() - * @throws IllegalStateException if variant is not of the requested type - */ - public Dispatch getDispatchRef() { - if ((this.getvt() & VariantDispatch) == VariantDispatch && - (this.getvt() & VariantByref) == VariantByref) { - return toDispatch(); - } else { - throw new IllegalStateException( - "getDispatchRef() only legal on byRef Variants of type VariantDispatch, not "+this.getvt()); - } - } - - /** - * @deprecated superceded by SafeArray - * @throws com.jacob.com.NotImplementedException - */ - public void putVariantArrayRef(Variant[] in) { - throw new NotImplementedException("Not implemented"); - } - - /** - * @deprecated superceded by SafeArray - * @throws com.jacob.com.NotImplementedException - */ - public Variant[] getVariantArrayRef() { - throw new NotImplementedException("Not implemented"); - } - - /** - * Converts variant to the passed in type by converting the underlying - * windows variant structure. private so folks use public java method - * @param in the desired resulting type - */ - private native void changeVariantType(short in); - - /** - * Cover for native method so we can cover it. - *

    - * This cannot convert an object to a byRef. - * It can convert from byref to not byref - * @param in type to convert this variant too - * @return Variant returns this same object so folks can change when replacing calls - * toXXX() with changeType().getXXX() - */ - public Variant changeType(short in) { - changeVariantType((short) in); - return this; - } - - /** - * I don't know what this is. Is it some legacy (pre 1.8) thing? - * @deprecated - * @return this object as a dispatch object by calling toDispatch() - */ - public Object toScriptObject() { - return toDispatch(); - } - - /** - * public constructor, initializes and sets type to VariantEmpty - */ - public Variant() { - this(null,false); - } - - /** - * Constructor that accepts a primitive rather than an object - * @param in - */ - public Variant(int in) { - this(new Integer(in)); - } - - /** - * Constructor that accepts a primitive rather than an object - * @param in - */ - public Variant(double in) { - this(new Double(in)); - } - - /** - * Constructor that accepts a primitive rather than an object - * @param in - */ - public Variant(boolean in) { - this(new Boolean(in)); - } - - /** - * Convenience constructor that calls the main one with - * a byRef value of false - * @param in object to be made into variant - */ - public Variant(Object in) { - this(in, false); - } - - /** - * constructor that accepts the data object and informaton about - * whether this is by reference or not. - * @param pValueObject a null object sets this to "empty" - * @param fByRef - */ - public Variant(Object pValueObject, boolean fByRef) { - init(); - if (pValueObject == null) { - putEmpty(); - } else if (pValueObject instanceof Integer) { - if (fByRef) - putIntRef(((Integer) pValueObject).intValue()); - else - putInt(((Integer) pValueObject).intValue()); - } else if (pValueObject instanceof Short) { - if (fByRef) - putShortRef(((Short) pValueObject).shortValue()); - else - putShort(((Short) pValueObject).shortValue()); - } else if (pValueObject instanceof String) { - if (fByRef) - putStringRef((String) pValueObject); - else - putString((String) pValueObject); - } else if (pValueObject instanceof Boolean) { - if (fByRef) - putBooleanRef(((Boolean) pValueObject).booleanValue()); - else - putBoolean(((Boolean) pValueObject).booleanValue()); - } else if (pValueObject instanceof Double) { - if (fByRef) - putDoubleRef(((Double) pValueObject).doubleValue()); - else - putDouble(((Double) pValueObject).doubleValue()); - } else if (pValueObject instanceof Float) { - if (fByRef) - putFloatRef(((Float) pValueObject).floatValue()); - else - putFloat(((Float) pValueObject).floatValue()); - } else if (pValueObject instanceof BigDecimal) { - if (fByRef) - putDecimalRef(((BigDecimal) pValueObject)); - else - putDecimal(((BigDecimal) pValueObject)); - } else if (pValueObject instanceof Byte){ - if (fByRef){ - putByteRef(((Byte)pValueObject).byteValue()); - } else { - putByte(((Byte)pValueObject).byteValue()); - } - } else if (pValueObject instanceof Date){ - if (fByRef){ - putDateRef((Date) pValueObject); - } else { - putDate((Date)pValueObject); - } - } else if (pValueObject instanceof SafeArray) { - if (fByRef) - putSafeArrayRef((SafeArray) pValueObject); - else - putSafeArray((SafeArray) pValueObject); - } else if (pValueObject instanceof Dispatch){ - if (fByRef) - putDispatchRef((Dispatch)pValueObject); - else - putDispatch((Dispatch)pValueObject); - } else if (pValueObject instanceof Variant){ - // newly added 1.12-pre6 - putVariant((Variant)pValueObject); - } else { - // should really throw an illegal argument exception if its an invalid type - if (fByRef) - putObjectRef(pValueObject); - else - putObject(pValueObject); - } - } - - /** - * Returns the variant type via a native method call - * @return short one of the VT_xx types - */ - private native short getVariantType(); - - /** - * Reports the type of the underlying Variant object - * @return returns the variant type as a short, one of the Variantxxx - * values defined as statics in this class. returns VariantNull if not initialized - * @throws IllegalStateException if there is no underlying windows data structure - */ - public short getvt(){ - if (m_pVariant != 0){ - return getVariantType(); - } else { - throw new IllegalStateException("uninitialized Variant"); - } - } - - /** - * attempts to return the contents of this Variant as a short - * (after possible conversion) - * @deprecated callers should use changeType() followed by getShort() - * @return short - */ - public short toShort() { - this.changeType(Variant.VariantShort); - return getShort(); - } - - /** - * now private so only this object can asccess was: call this to explicitly - * release the com object before gc - * - */ - private native void release(); - - protected native void init(); - - /* - * (non-Javadoc) - * - * @see java.lang.Object#finalize() - */ - protected void finalize() { - safeRelease(); - } - - /** - * returns true if the passed in Variant is a constant that should not be freed - * @param pVariant - * @return boolian that is true if Variant is a type of constant, - * VT_FALSE, VT_TRUE, VT_MISSING, DEFAULT - */ - protected boolean objectIsAConstant(Variant pVariant){ - if (pVariant == VT_FALSE || - pVariant == VT_TRUE || - pVariant == VT_MISSING || - pVariant == DEFAULT){ - return true; - } else { - return false; - } - - } - - /** - * This will release the "C" memory for the Variant - * unless this Variant is one of the constants in which case - * we don't want to release the memory. - *

    - * @see com.jacob.com.JacobObject#safeRelease() - */ - public void safeRelease() { - // The well known constants should not be released. - // Unfortunately this doesn't fix any other classes that are - // keeping constants around in their static ivars. - // those will still be busted. - // - // The only inconcistency here is that we leak + private native void putVariantDate(double in); + + /** + * set the content of this variant to a date (VT_DATE|VT_BYREF) + * + * @param in + */ + private native void putVariantDateRef(double in); + + /** + * private JNI method called by putDecimal + * + * @param signum + * sign + * @param scale + * BigDecimal's scale + * @param lo + * low 32 bits + * @param mid + * middle 32 bits + * @param hi + * high 32 bits + */ + private native void putVariantDec(int signum, byte scale, int lo, int mid, + int hi); + + /** + * private JNI method called by putDecimalRef + * + * @param signum + * sign + * @param scale + * BigDecimal's scale + * @param lo + * low 32 bits + * @param mid + * middle 32 bits + * @param hi + * high 32 bits + */ + private native void putVariantDecRef(int signum, byte scale, int lo, + int mid, int hi); + + /** + * the JNI implementation for putDispatch() so that we can screen the + * incoming dispatches in putDispatch() before this is invoked + * + * @param in + * should be a dispatch object + */ + private native void putVariantDispatch(Object in); + + private native void putVariantDouble(double in); + + /** + * set the content of this variant to a double (VT_R8|VT_BYREF) + * + * @param in + */ + private native void putVariantDoubleRef(double in); + + /** + * Sets the type to VariantEmpty. No values needed + */ + private native void putVariantEmpty(); + + private native void putVariantError(int in); + + private native void putVariantErrorRef(int in); + + /** + * fills the Variant with a float and sets the type to float + * + * @param in + */ + private native void putVariantFloat(float in); + + private native void putVariantFloatRef(float in); + + /** + * set the value of this variant and set the type + * + * @param in + */ + private native void putVariantInt(int in); + + /** + * set the content of this variant to an int (VT_I4|VT_BYREF) + * + * @param in + */ + private native void putVariantIntRef(int in); + + private native void putVariantLong(long in); + + private native void putVariantLongRef(long in); + + /** + * sets the type to VT_ERROR and the error message to DISP_E_PARAMNOTFOIUND + */ + private native void putVariantNoParam(); + + /** + * Sets the type to VariantDispatch and sets the value to null Equivalent to + * VB's nothing + */ + private native void putVariantNothing(); + + /** + * Set this Variant's type to VT_NULL (the VB equivalent of NULL) + */ + private native void putVariantNull(); + + private native void putVariantSafeArray(SafeArray in); + + private native void putVariantSafeArrayRef(SafeArray in); + + /** + * set the content of this variant to a short (VT_I2) + * + * @param in + */ + private native void putVariantShort(short in); + + /** + * set the content of this variant to a short (VT_I2|VT_BYREF) + * + * @param in + */ + private native void putVariantShortRef(short in); + + private native void putVariantString(String in); + + /** + * set the content of this variant to a string (VT_BSTR|VT_BYREF) + * + * @param in + */ + private native void putVariantStringRef(String in); + + /** + * All VariantVariant type variants are BYREF. + * + * Set the content of this variant to a string (VT_VARIANT|VT_BYREF). + * + * Added 1.12 pre 6 - VT_VARIANT support is at an alpha level + * + * @param in + * variant to be wrapped + * + */ + private native void putVariantVariant(Variant in); + + /** + * now private so only this object can access was: call this to explicitly + * release the com object before gc + * + */ + private native void release(); + + /** + * This will release the "C" memory for the Variant unless this Variant is + * one of the constants in which case we don't want to release the memory. + *

    + * + * @see com.jacob.com.JacobObject#safeRelease() + */ + public void safeRelease() { + // The well known constants should not be released. + // Unfortunately this doesn't fix any other classes that are + // keeping constants around in their static ivars. + // those will still be busted. + // + // The only inconsistency here is that we leak // when this class is unloaded because we won't // free the memory even if the constants are being - // finalized. this is not a big deal at all. + // finalized. this is not a big deal at all. // another way around this would be to create the constants // in their own thread so that they would never be released - if (!objectIsAConstant(this)){ - super.safeRelease(); - if (m_pVariant != 0) { - release(); - m_pVariant = 0; - } else { - // looks like a double release - // this should almost always happen due to gc - // after someone has called ComThread.Release - if (isDebugEnabled()) { - debug("Variant: " + this.hashCode() - + " double release"); - //Throwable x = new Throwable(); - //x.printStackTrace(); - } - } - } else { - if (isDebugEnabled()) { - debug("Variant: " + this.hashCode() - + " don't want to release a constant"); - } - } - } + if (!objectIsAConstant(this)) { + super.safeRelease(); + if (m_pVariant != 0) { + release(); + m_pVariant = 0; + } else { + // looks like a double release + // this should almost always happen due to gc + // after someone has called ComThread.Release + if (isDebugEnabled()) { + debug("Variant: " + this.hashCode() + " double release"); + // Throwable x = new Throwable(); + // x.printStackTrace(); + } + } + } else { + if (isDebugEnabled()) { + debug("Variant: " + this.hashCode() + + " don't want to release a constant"); + } + } + } - /** - * @deprecated superceded by SafeArray - * @return nothing because this method is not implemented - * @throws com.jacob.com.NotImplementedException - */ - public Variant[] toVariantArray() { - throw new NotImplementedException("Not implemented"); - } + /** + * this is supposed to cause the underlying variant object struct to be + * rebuilt from a previously serialized byte array. + * + * @param ba + */ + protected native void SerializationReadFromBytes(byte[] ba); - /** - * @deprecated superceded by SafeArray - * @return nothing because this method is not implemented - * @throws com.jacob.com.NotImplementedException - */ - public Object toByteArray() { - throw new NotImplementedException("Not implemented"); - } + /** + * this is supposed to create a byte array that represents the underlying + * variant object structure + */ + protected native byte[] SerializationWriteToBytes(); - /** - * is the variant null or empty or error or null dispatch - * @return true if it is null or false if not - */ - private native boolean isVariantConsideredNull(); + /** + * @deprecated should be replaced by changeType() followed by getBoolean() + * @return the value of this variant as boolean (after possible conversion) + */ + @Deprecated + public boolean toBoolean() { + changeType(Variant.VariantBoolean); + return getBoolean(); + } - /** - * - * @return returns true if the variant is considered null - * @throws IllegalStateException if there is no underlying windows memory - */ - public boolean isNull(){ - getvt(); - return isVariantConsideredNull(); - } - - /** - * this is supposed to create a byte array that represents the underlying - * variant object struct - */ - protected native byte[] SerializationWriteToBytes(); - - /** - * this is supposed to cause the underlying variant object struct to - * be rebuilt from a previously serialized byte array. - * @param ba - */ - protected native void SerializationReadFromBytes(byte[] ba); - - /*===================================================================== - * - * - *=====================================================================*/ - /** - * 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. - *

    - * Unlike other toXXX() methods, it does not do a type conversion - * except for special data types (it shouldn't do any!) + /** + * attempts to return the content of this variant as a double (after + * possible conversion) + * + * @deprecated should be replaced by changeType() followed by getByte() + * @return byte + */ + @Deprecated + public byte toByte() { + changeType(Variant.VariantByte); + return getByte(); + } + + /** + * @deprecated superseded by SafeArray + * @return nothing because this method is not implemented + * @throws com.jacob.com.NotImplementedException + */ + @Deprecated + public Object toByteArray() { + throw new NotImplementedException("Not implemented"); + } + + /** + * @deprecated superseded by SafeArray + * @return never returns anything + * @throws com.jacob.com.NotImplementedException + */ + @Deprecated + public Object toCharArray() { + throw new NotImplementedException("Not implemented"); + } + + /** + * @deprecated should be replaced by changeType() followed by getCurrency + * @return the content of this variant as a long representing a monetary + * amount + */ + @Deprecated + public Currency toCurrency() { + changeType(Variant.VariantCurrency); + return getCurrency(); + } + + /** + * @deprecated should use changeType() followed by getDate() + * @return the value of this variant as a date (after possible conversion) + */ + @Deprecated + public double toDate() { + changeType(VariantDate); + return getDate(); + } + + /** + * @return the content of this variant as a Dispatch object (after possible + * conversion) + */ + public Dispatch toDispatch() { + // now make the native call + return toVariantDispatch(); + } + + /** + * @deprecated should call changeType() then getDouble() + * @return the content of this variant as a double (after possible + * conversion) + */ + @Deprecated + public double toDouble() { + changeType(Variant.VariantDouble); + return getDouble(); + } + + /** @return the value of this variant as an enumeration (java style) */ + public native EnumVariant toEnumVariant(); + + /** + * converts to an error type and returns the error + * + * @deprecated should use changeType() followed by getError() + * @return the error as an int (after conversion) + */ + @Deprecated + public int toError() { + changeType(Variant.VariantError); + return getError(); + } + + /** + * attempts to return the contents of this variant as a float (after + * possible conversion) + * + * @deprecated should use changeType() and getFloat() instead + * @return float + */ + @Deprecated + public float toFloat() { + changeType(Variant.VariantFloat); + return getFloat(); + } + + /** + * @deprecated should use changeType() followed by getInt() + * @return the value of this variant as an int (after possible conversion) + */ + @Deprecated + public int toInt() { + changeType(VariantInt); + return getInt(); + } + + /** + * Returns the windows time contained in this Variant as a Java Date + * converts to a date like many of the other toXXX() methods SF 959382. *

    - * Converts Variant.VariantArray types to SafeArrays + * This method added 12/2005 for possible use by jacobgen instead of its + * conversion code + *

    + * This does not convert the data + * + * @deprecated callers should use getDate() + * @return java.util.Date version of this variant if it is a date, otherwise + * null + * + */ + @Deprecated + public Date toJavaDate() { + changeType(Variant.VariantDate); + return getJavaDate(); + } + + /** + * Convert a JACOB Variant value to a Java object (type conversions). + * provided in Sourceforge feature request 959381. See + * JavaVariantConverter..convertVariantTJavaObject(Variant) for more + * information. + * * @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 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 */ public Object toJavaObject() throws JacobException { - Object result = null; - - short type = this.getvt(); //variant type - - if ((type & Variant.VariantArray) == VariantArray) { //array returned? - SafeArray array = null; - type = (short) (type - Variant.VariantArray); - array = this.toSafeArray(false); - //result = toJava(array); - 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(this.getShort()); - break; - case Variant.VariantShort | Variant.VariantByref : //2 - result = new Short(this.getShortRef()); - break; - case Variant.VariantInt : //3 - result = new Integer(this.getInt()); - break; - case Variant.VariantInt | Variant.VariantByref: //3 - result = new Integer(this.getIntRef()); - break; - case Variant.VariantFloat : //4 - result = new Float(this.getFloat()); - break; - case Variant.VariantFloat | Variant.VariantByref: //4 - result = new Float(this.getFloatRef()); - break; - case Variant.VariantDouble : //5 - result = new Double(this.getDouble()); - break; - case Variant.VariantDouble | Variant.VariantByref: //5 - result = new Double(this.getDoubleRef()); - break; - case Variant.VariantCurrency : //6 - result = new Long(this.getCurrency()); - break; - case Variant.VariantCurrency | Variant.VariantByref: //6 - result = new Long(this.getCurrencyRef()); - break; - case Variant.VariantDate : //7 - result = this.getJavaDate(); - break; - case Variant.VariantDate | Variant.VariantByref : //7 - result = this.getJavaDateRef(); - break; - case Variant.VariantString : //8 - result = this.getString(); - break; - case Variant.VariantString | Variant.VariantByref: //8 - result = this.getStringRef(); - break; - case Variant.VariantDispatch : //9 - result = this.getDispatch(); - break; - case Variant.VariantDispatch | Variant.VariantByref: //9 - result = this.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(this.getBoolean()); - break; - case Variant.VariantBoolean | Variant.VariantByref: //11 - result = new Boolean(this.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 = getVariant(); - break; - case Variant.VariantObject : //13 - result = new NotImplementedException("toJavaObject() Not implemented for VariantObject"); - break; - case Variant.VariantDecimal : //14 - result = getDecimal(); - break; - case Variant.VariantDecimal | Variant.VariantByref: //14 - result = getDecimalRef(); - break; - case Variant.VariantByte : //17 - result = new Byte(this.getByte()); - break; - case Variant.VariantByte | Variant.VariantByref: //17 - result = new Byte(this.getByteRef()); - 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() + return VariantUtilities.variantToObject(this); + } + + /** + * Acts a a cover for toDispatch. This primarily exists to support jacobgen. + * + * @deprecated this is a cover for toDispatch(); + * @return Object returned by toDispatch() + * @see Variant#toDispatch() instead + */ + @Deprecated + public Object toObject() { + return toDispatch(); + } + + /** + * By default toSafeArray makes a deep copy due to the fact that this + * Variant owns the embedded SafeArray and will destroy it when it gc's + * calls toSafeArray(true). + * + * @return the object converted to a SafeArray + */ + public SafeArray toSafeArray() { + // verify we haven't been released yet + getvt(); + return toSafeArray(true); + } + + /** + * This lets folk turn into a safe array without a deep copy. Should this + * API be public? + * + * @param deepCopy + * @return SafeArray constructed + */ + public SafeArray toSafeArray(boolean deepCopy) { + // verify we haven't been released yet + getvt(); + return toVariantSafeArray(deepCopy); + } + + /** + * I don't know what this is. Is it some legacy (pre 1.8) thing? + * + * @deprecated + * @return this object as a dispatch object by calling toDispatch() + */ + @Deprecated + public Object toScriptObject() { + return toDispatch(); + } + + /** + * attempts to return the contents of this Variant as a short (after + * possible conversion) + * + * @deprecated callers should use changeType() followed by getShort() + * @return short + */ + @Deprecated + public short toShort() { + this.changeType(Variant.VariantShort); + return getShort(); + } + + /** + * This method now correctly implements java toString() semantics Attempts + * to return the content of this variant as a string + *

      + *
    • "not initialized" if not initialized + *
    • "null" if VariantEmpty, + *
    • "null" if VariantError + *
    • "null" if VariantNull + *
    • the value if we know how to describe one of that type + *
    • three question marks if can't convert + * + * @return String value conversion, + * @throws IllegalStateException + * if there is no underlying windows data structure + */ + public String toString() { + try { + // see if we are in a legal state + getvt(); + } catch (IllegalStateException ise) { + return ""; + } + if (getvt() == VariantEmpty || getvt() == VariantError + || getvt() == VariantNull) { + return "null"; + } + if (getvt() == VariantString) { + return getString(); + } + try { + Object foo = toJavaObject(); + // rely on java objects to do the right thing + return foo.toString(); + } catch (NotImplementedException nie) { + // some types do not generate a good description yet + return "Description not available for type: " + getvt(); + } + } + + /** + * Exists to support jacobgen. This would be deprecated if it weren't for + * jacobgen + * + * @deprecated superseded by "this" + * @return this same object + */ + @Deprecated + public Variant toVariant() { + return this; + } + + /** + * @deprecated superseded by SafeArray + * @return nothing because this method is not implemented + * @throws com.jacob.com.NotImplementedException + */ + @Deprecated + public Variant[] toVariantArray() { + throw new NotImplementedException("Not implemented"); + } + + /** + * native method used by toDispatch() + * + * @return + */ + private native Dispatch toVariantDispatch(); + + private native SafeArray toVariantSafeArray(boolean deepCopy); + + /* + * ===================================================================== + * + * + * ===================================================================== + */ + + /** + * Clear the content of this variant + */ + public native void VariantClear(); + } \ No newline at end of file diff --git a/src/com/jacob/com/VariantUtilities.java b/src/com/jacob/com/VariantUtilities.java new file mode 100644 index 0000000..62a3995 --- /dev/null +++ b/src/com/jacob/com/VariantUtilities.java @@ -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. + *

      + * Unlike other toXXX() methods, it does not do a type conversion except for + * special data types (it shouldn't do any!) + *

      + * 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. + *

      + * 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; + } +} diff --git a/src/com/jacob/com/VariantViaEvent.java b/src/com/jacob/com/VariantViaEvent.java index fbc2f2a..649d2bc 100644 --- a/src/com/jacob/com/VariantViaEvent.java +++ b/src/com/jacob/com/VariantViaEvent.java @@ -19,15 +19,16 @@ */ package com.jacob.com; -/** - * a public class to variant that is used - * to track which variant objects are created by event callbacks - * This is soley used for that purpose. +/** + * a public class to variant that is used to track which variant objects are + * created by event callbacks This is solely used for that purpose. */ public class VariantViaEvent extends Variant { - public VariantViaEvent(){ - super(); - } + /** + * Standard constructor used by JNI event handling layer + */ + public VariantViaEvent() { + super(); + } } - diff --git a/src/com/jacob/com/WrongThreadException.java b/src/com/jacob/com/WrongThreadException.java index 9de5685..938e40c 100644 --- a/src/com/jacob/com/WrongThreadException.java +++ b/src/com/jacob/com/WrongThreadException.java @@ -23,24 +23,25 @@ package com.jacob.com; * thrown in util.cpp */ public class WrongThreadException extends JacobException { - /** + /** * identifier generated by Eclipse */ private static final long serialVersionUID = 6308780364980228692L; /** - * standard 0 arg constructor with no message - * - */ - public WrongThreadException() { - super("No Message Provided."); - } + * standard 0 arg constructor with no message + * + */ + public WrongThreadException() { + super("No Message Provided."); + } - /** - * standard constructor with a string message - * @param s - */ - public WrongThreadException(String s) { - super(s); - } + /** + * standard constructor with a string message + * + * @param s + */ + public WrongThreadException(String s) { + super(s); + } } \ No newline at end of file diff --git a/unittest/com/jacob/com/ActiveXComponentFactoryTest.java b/unittest/com/jacob/com/ActiveXComponentFactoryTest.java index 7b3c340..71f4c26 100644 --- a/unittest/com/jacob/com/ActiveXComponentFactoryTest.java +++ b/unittest/com/jacob/com/ActiveXComponentFactoryTest.java @@ -4,56 +4,112 @@ import com.jacob.activeX.ActiveXComponent; import com.jacob.test.BaseTestCase; /** - * This exercises the two Dispatch factor methods that let you - * control whether you create a new running COM object or connect to an existing one + * This exercises the two Dispatch factor methods that let you control whether + * you create a new running COM object or connect to an existing one *

      - * 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. + * 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 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); 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"; - ActiveXComponent mTryConnectingFirst = ActiveXComponent.connectToActiveInstance(mApplicationId); - if (mTryConnectingFirst != null ){ - mTryConnectingFirst.invoke("Quit",new Variant[] {}); - System.out.println("Was able to connect to MSWord when hadn't started it"); + ActiveXComponent mTryConnectingFirst = ActiveXComponent + .connectToActiveInstance(mApplicationId); + if (mTryConnectingFirst != null) { + mTryConnectingFirst.invoke("Quit", new Variant[] {}); + System.out + .println("Was able to connect to MSWord when hadn't started it"); } 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"); - ActiveXComponent mTryStartingSecond = ActiveXComponent.createNewInstance(mApplicationId); - if (mTryStartingSecond == null){ + ActiveXComponent mTryStartingSecond = ActiveXComponent + .createNewInstance(mApplicationId); + if (mTryStartingSecond == null) { System.out.println("was unable to start up MSWord "); } else { System.out.println("Correctly could start MSWord"); } - ActiveXComponent mTryConnectingThird = ActiveXComponent.connectToActiveInstance(mApplicationId); - if (mTryConnectingThird == null ){ + ActiveXComponent mTryConnectingThird = ActiveXComponent + .connectToActiveInstance(mApplicationId); + if (mTryConnectingThird == null) { fail("Was unable able to connect to MSWord after previous startup"); } else { System.out.println("Stopping MSWord"); // 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); - ActiveXComponent mTryConnectingFourth = ActiveXComponent.connectToActiveInstance(mApplicationId); - if (mTryConnectingFourth != null ){ - mTryConnectingFourth.invoke("Quit",new Variant[] {}); + ActiveXComponent mTryConnectingFourth = ActiveXComponent + .connectToActiveInstance(mApplicationId); + if (mTryConnectingFourth != null) { + mTryConnectingFourth.invoke("Quit", new Variant[] {}); fail("Was able to connect to MSWord that was stopped"); } 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) { e.printStackTrace(); fail("Caught COM exception"); } finally { - //System.out.println("About to sleep for 2 seconds so we can bask in the glory of this success"); - //Thread.sleep(2000); + // System.out.println("About to sleep for 2 seconds so we can bask + // in the glory of this success"); + // Thread.sleep(2000); ComThread.Release(); ComThread.quitMainSTA(); } diff --git a/unittest/com/jacob/com/DateUtilitiesTest.java b/unittest/com/jacob/com/DateUtilitiesTest.java index ee9792d..e7b7f50 100644 --- a/unittest/com/jacob/com/DateUtilitiesTest.java +++ b/unittest/com/jacob/com/DateUtilitiesTest.java @@ -9,37 +9,45 @@ import junit.framework.TestCase; /** * test cases that should exercise the new date conversion code *

      - * 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 void testDateUtilities(){ - Date now = new Date(); - double comTimeForNow = DateUtilities.convertDateToWindowsTime(now); - Date retrievedNow = DateUtilities.convertWindowsTimeToDate(comTimeForNow); - if (!now.equals(retrievedNow)){ - fail("DateUtilities Date Test failed " +now+ " != " +retrievedNow ); - } else { - System.out.println("DateUtilities Date Test passed"); - } - - } - - public void testBeginningOfWindowsTime(){ - // 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){ - fail("Beginning of windows time test failed " - +comTimeForBeginningOfWindowsTime); - } else { - System.out.println("Beginning of windows time test passed"); - } - - } - + /** + * verify date conversion to and from java + */ + public void testDateUtilities() { + Date now = new Date(); + double comTimeForNow = DateUtilities.convertDateToWindowsTime(now); + Date retrievedNow = DateUtilities + .convertWindowsTimeToDate(comTimeForNow); + if (!now.equals(retrievedNow)) { + fail("DateUtilities Date Test failed " + now + " != " + + retrievedNow); + } else { + System.out.println("DateUtilities Date Test passed"); + } + + } + + /** + * Verify that the start of time is when we think it is. + */ + public void testBeginningOfWindowsTime() { + // 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) { + fail("Beginning of windows time test failed " + + comTimeForBeginningOfWindowsTime); + } else { + System.out.println("Beginning of windows time test passed"); + } + + } } diff --git a/unittest/com/jacob/com/DispatchNullProgramId.java b/unittest/com/jacob/com/DispatchNullProgramId.java index 2df6805..5146562 100644 --- a/unittest/com/jacob/com/DispatchNullProgramId.java +++ b/unittest/com/jacob/com/DispatchNullProgramId.java @@ -3,31 +3,35 @@ package com.jacob.com; import com.jacob.test.BaseTestCase; /** - * This test verifies that the Dispatch object protects itself when - * the constructor is called with a null program id. - * Prior to this protection, the VM might crash.m + * This test verifies that the Dispatch object protects itself when the + * constructor is called with a null program id. Prior to this protection, the + * VM might crash.m *

      - * 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. + * 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 DispatchNullProgramId extends BaseTestCase { - public void testNullProgramId(){ + /** + * Verify that dispatch constructors are protected from null program ids. + */ + public void testNullProgramId() { try { String nullParam = null; new Dispatch(nullParam); fail("the dispatch failed to protect itself from null program ids"); - } catch (IllegalArgumentException iae){ - System.out.println( - "the dispatch protected itself from null program ids"); + } catch (IllegalArgumentException iae) { + System.out + .println("the dispatch protected itself from null program ids"); } try { String nullParam = ""; new Dispatch(nullParam); fail("the dispatch failed to protect itself from empty string program ids"); - } catch (IllegalArgumentException iae){ - System.out.println( - "the dispatch protected itself from empty string program ids"); + } catch (IllegalArgumentException iae) { + System.out + .println("the dispatch protected itself from empty string program ids"); } } } diff --git a/unittest/com/jacob/com/DispatchTest.java b/unittest/com/jacob/com/DispatchTest.java index 3b2f4b5..eef7dc1 100644 --- a/unittest/com/jacob/com/DispatchTest.java +++ b/unittest/com/jacob/com/DispatchTest.java @@ -1,24 +1,20 @@ package com.jacob.com; -import java.util.Date; - import com.jacob.test.BaseTestCase; /** * Test some of the Dispatch utility methods - *

      - * 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. + *

      + * 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 DispatchTest extends BaseTestCase { - public void testDispatch() { - Date testDate = new Date(); - Variant fromDate = Dispatch.obj2variant(testDate); - Date returnedDate = fromDate.getJavaDate(); - //System.out.println("test date is "+testDate); - //System.out.println("VariantDate is "+fromDate.getJavaDate()); - assertTrue("Could not call obj2variant(Date) and get it to work", - testDate.equals(returnedDate)); - } + /** + * Dummy test until someone gets their act together + */ + public void testDispatch() { + // what should we test + } } diff --git a/unittest/com/jacob/com/DispatchValidDispatchTest.java b/unittest/com/jacob/com/DispatchValidDispatchTest.java index 6f37ec4..54bf635 100644 --- a/unittest/com/jacob/com/DispatchValidDispatchTest.java +++ b/unittest/com/jacob/com/DispatchValidDispatchTest.java @@ -4,27 +4,38 @@ import com.jacob.test.BaseTestCase; /** * Test armoring of dispatch static methods - *

      - * 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. + *

      + * 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 DispatchValidDispatchTest extends BaseTestCase { - public void testThrowIllegalArgumentException() { - try { - Dispatch.call(null, 0); - fail("Failed to throw IllegalArgumentException"); - } catch (IllegalArgumentException iae){ - System.out.println("Caught correct IllegalArgumentException: "+iae); - } - } - 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); - } - } + /** + * force an IllegalArgumentException to verify the utility method throws + * correctly. + */ + public void testThrowIllegalArgumentException() { + try { + Dispatch.call(null, 0); + fail("Failed to throw IllegalArgumentException"); + } catch (IllegalArgumentException iae) { + System.out.println("Caught correct IllegalArgumentException: " + + iae); + } + } + + /** + * 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); + } + } } diff --git a/unittest/com/jacob/com/JacobObjectTest.java b/unittest/com/jacob/com/JacobObjectTest.java index 60ead35..47da8a7 100644 --- a/unittest/com/jacob/com/JacobObjectTest.java +++ b/unittest/com/jacob/com/JacobObjectTest.java @@ -5,16 +5,18 @@ import com.jacob.test.BaseTestCase; /** * This will eventually be changed to a unit test. *

      - * 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. + * 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 JacobObjectTest extends BaseTestCase { - - public void testBuildVersion(){ - System.out.println("build version is "+JacobObject.getBuildVersion()); - System.out.println("build date is "+JacobObject.getBuildDate()); - } - - + /** + * verify the build version and date functions work correctly + */ + public void testBuildVersion() { + System.out.println("build version is " + JacobReleaseInfo.getBuildVersion()); + System.out.println("build date is " + JacobReleaseInfo.getBuildDate()); + } + } diff --git a/unittest/com/jacob/com/LibraryLoaderTest.java b/unittest/com/jacob/com/LibraryLoaderTest.java new file mode 100644 index 0000000..70ddd48 --- /dev/null +++ b/unittest/com/jacob/com/LibraryLoaderTest.java @@ -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. + * + *

      + * 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)); + } + } +} diff --git a/unittest/com/jacob/com/ROT2Test.java b/unittest/com/jacob/com/ROT2Test.java index fb0d6ab..ff30cf1 100644 --- a/unittest/com/jacob/com/ROT2Test.java +++ b/unittest/com/jacob/com/ROT2Test.java @@ -14,6 +14,9 @@ import com.jacob.test.BaseTestCase; */ public class ROT2Test extends BaseTestCase { + /** + * runs a multi-threaded test + */ public void testDoesNotBlowUp() { ROT2TestThread threads[] = new ROT2TestThread[4]; for (int i = 0; i < threads.length; i++) { @@ -29,12 +32,14 @@ public class ROT2Test extends BaseTestCase { */ public class ROT2TestThread extends Thread { - private java.util.List ThreadObjects; + private java.util.List ThreadObjects; private int initialRunSize = 0; /** * @param arg0 + * @param iStartCount + * the initial number of threads */ public ROT2TestThread(String arg0, int iStartCount) { 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 * 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 // we need to create these in the thread so they end up in the right // ROT table - ThreadObjects = new java.util.ArrayList(initialRunSize); + ThreadObjects = new java.util.ArrayList(initialRunSize); for (int i = 0; i < initialRunSize; i++) { // create the object 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. - * That would really screw the ROT! + * Another test would be to override this to always return the same + * name. That would really screw the ROT! * * @see java.lang.Object#toString() */ diff --git a/unittest/com/jacob/com/ROT3Test.java b/unittest/com/jacob/com/ROT3Test.java index 3db3566..798c420 100644 --- a/unittest/com/jacob/com/ROT3Test.java +++ b/unittest/com/jacob/com/ROT3Test.java @@ -3,8 +3,9 @@ package com.jacob.com; import com.jacob.test.BaseTestCase; /** - * This tries to exercise ROT's garbage collection This is named this way because - * the build.xml ignores files ending in Test when building the binary zip file + * This tries to exercise ROT's garbage collection This is named this way + * because the build.xml ignores files ending in Test when building the binary + * zip file * * This will eventually be changed to a unit test. * @@ -15,6 +16,9 @@ import com.jacob.test.BaseTestCase; */ public class ROT3Test extends BaseTestCase { + /** + * runs a multi-threaded test + */ public void testROTVersion3() { ROT3TestThread threads[] = new ROT3TestThread[4]; for (int i = 0; i < threads.length; i++) { @@ -30,12 +34,14 @@ public class ROT3Test extends BaseTestCase { */ public class ROT3TestThread extends Thread { - private java.util.List variansCreatedInThisThread; + private java.util.List variansCreatedInThisThread; private int initialRunSize = 0; /** * @param arg0 + * @param iStartCount + * the number of initial threads */ public ROT3TestThread(String arg0, int iStartCount) { 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 * but not a even number, add 1 new object 3) stop when size is 1. * * @see java.lang.Runnable#run() */ + @SuppressWarnings("deprecation") public void run() { // something that keeps object references around // so the gc can't collect them // we need to create these in the thread so they end up in the right // ROT table - variansCreatedInThisThread = new java.util.ArrayList(initialRunSize); + variansCreatedInThisThread = new java.util.ArrayList( + initialRunSize); for (int i = 0; i < initialRunSize; i++) { // create the object Variant aNewVariant = new Variant(getName() + "_" + i); @@ -92,9 +100,8 @@ public class ROT3Test extends BaseTestCase { if (!ROT.USE_AUTOMATIC_GARBAGE_COLLECTION) { // uses deprecated API to set up a special situation // because this is an ROT test - ROT - .removeObject((JacobObject) variansCreatedInThisThread - .get(i - 1)); + ROT.removeObject(variansCreatedInThisThread + .get(i - 1)); } variansCreatedInThisThread.remove(i - 1); } diff --git a/unittest/com/jacob/com/ROTTest.java b/unittest/com/jacob/com/ROTTest.java index dff211d..38b032b 100644 --- a/unittest/com/jacob/com/ROTTest.java +++ b/unittest/com/jacob/com/ROTTest.java @@ -1,121 +1,133 @@ package com.jacob.com; + import com.jacob.test.BaseTestCase; + /** * This tries to exercise ROT's garbage collection * * This will eventually be changed to a unit test. *

      - * 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. + * 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 ROTTest extends BaseTestCase { - - /** - * verify the SystemProperty (classname).PutInROT functions as expected. - * A value of false means instances of the class are not put in the ROT - * Any o ther value means they are - */ - public void testDontFillROTSystemProperty(){ - debug("testDontFillROTSystemProperty: started"); - // Make sure the class is loaded before running any of the tests - // class to load and any pre-defined Variants (FALSE and TRUE) to be created immediately - VariantViaEvent.class.getName(); - if (ROT.getThreadObjects(true).entrySet().size() < 1){ - debug("Failure: ROT should have objects in it as soon as Variant class loaded."); - } + /** + * verify the SystemProperty (classname).PutInROT functions as expected. A + * value of false means instances of the class are not put in the ROT Any o + * ther value means they are + */ + public void testDontFillROTSystemProperty() { + debug("testDontFillROTSystemProperty: started"); + // Make sure the class is loaded before running any of the tests + // class to load and any pre-defined Variants (FALSE and TRUE) to be + // created immediately + VariantViaEvent.class.getName(); + if (ROT.getThreadObjects(true).entrySet().size() < 1) { + 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"); - int countPriorToTest = ROT.getThreadObjects(true).entrySet().size(); - new VariantViaEvent(); - int countAfterAddWithoutROT = ROT.getThreadObjects(true).entrySet().size(); - if (countAfterAddWithoutROT != countPriorToTest){ - debug("Failure: count prior: "+countPriorToTest+ - " and count after without ROT was: "+countAfterAddWithoutROT); - } - - System.setProperty(VariantViaEvent.class.getName()+ROT.PUT_IN_ROT_SUFFIX,"true"); - 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() + + ROT.PUT_IN_ROT_SUFFIX, "false"); + int countPriorToTest = ROT.getThreadObjects(true).entrySet().size(); + new VariantViaEvent(); + int countAfterAddWithoutROT = ROT.getThreadObjects(true).entrySet() + .size(); + if (countAfterAddWithoutROT != countPriorToTest) { + debug("Failure: count prior: " + countPriorToTest + + " and count after without ROT was: " + + countAfterAddWithoutROT); + } - /** - * Needs documentation. This test looks broken - * - */ - public void testGCBehavior(){ - int sizeBeforeBuild = 0; - int sizeAfterBuild = 0; - int sizeBeforeGC = 0; - int sizeAfterGC = 0; - int loopSize = 10000; - int sizeExpectedAfterBuild = 0; + System.setProperty(VariantViaEvent.class.getName() + + ROT.PUT_IN_ROT_SUFFIX, "true"); + 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"); + } - - debug("testGCBehavior: started"); - debug("creating 10,000 object sets"); - // cause classes to get loaded and any static instances to be created - SafeArray.class.getName(); - Variant.class.getName(); - sizeBeforeBuild = ROT.getThreadObjects(false).size(); - sizeExpectedAfterBuild = ((loopSize*3)+sizeBeforeBuild); - for ( int i = 0 ; i < loopSize; i++){ - SafeArray a1 = new SafeArray(Variant.VariantVariant, 2); - a1.setVariant(0, new Variant("foo")); - a1.setVariant(1, new Variant("bar")); - } - sizeAfterBuild = ROT.getThreadObjects(false).size(); - if (sizeAfterBuild < sizeExpectedAfterBuild){ - debug("Something got GC'd: "+sizeAfterBuild); - } else if (sizeAfterBuild > sizeExpectedAfterBuild){ - debug("More: "+sizeAfterBuild+" than expected: "+sizeExpectedAfterBuild); - } else { - debug("They're all there"); - } - // add more to the VM - debug("Flooding Memory to force GC"); - for ( int i = 0 ; i <= loopSize*2; i++){ - new String("this is just some text to see if we can force gc "+i); - } - // storage will hold weak references until the next JacobObject is created - System.gc(); - sizeBeforeGC = ROT.getThreadObjects(false).size(); - debug("Objects left after flood and gc but before adding a new object that clean's up weak references: "+sizeBeforeGC); - debug("Creating single object. This adds one and causes ROT to clean up GC'd"); - new JacobObject(); - sizeAfterGC = ROT.getThreadObjects(false).size(); - debug("Objects left after adding one (caused weak ref objects to be removed): "+sizeAfterGC); - new JacobObject(); - if (ROT.getThreadObjects(false).size() != sizeAfterGC+1){ - debug("Unexpected number of objects after adding only one more "+ROT.getThreadObjects(false).size()); - } else { - debug("Found number expected after adding one more " +(sizeAfterGC+1) ); - } - ROT.clearObjects(); - if (ROT.getThreadObjects(false) == null){ - debug("ROT pool was destroyed as expected after clearObjects called."); - } 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); - } + /** + * Needs documentation. This test looks broken + * + */ + public void testGCBehavior() { + int sizeBeforeBuild = 0; + int sizeAfterBuild = 0; + int sizeBeforeGC = 0; + int sizeAfterGC = 0; + int loopSize = 10000; + int sizeExpectedAfterBuild = 0; + + debug("testGCBehavior: started"); + debug("creating 10,000 object sets"); + // cause classes to get loaded and any static instances to be created + SafeArray.class.getName(); + Variant.class.getName(); + sizeBeforeBuild = ROT.getThreadObjects(false).size(); + sizeExpectedAfterBuild = ((loopSize * 3) + sizeBeforeBuild); + for (int i = 0; i < loopSize; i++) { + SafeArray a1 = new SafeArray(Variant.VariantVariant, 2); + a1.setVariant(0, new Variant("foo")); + a1.setVariant(1, new Variant("bar")); + } + sizeAfterBuild = ROT.getThreadObjects(false).size(); + if (sizeAfterBuild < sizeExpectedAfterBuild) { + debug("Something got GC'd: " + sizeAfterBuild); + } else if (sizeAfterBuild > sizeExpectedAfterBuild) { + debug("More: " + sizeAfterBuild + " than expected: " + + sizeExpectedAfterBuild); + } else { + debug("They're all there"); + } + // add more to the VM + debug("Flooding Memory to force GC"); + for (int i = 0; i <= loopSize * 2; i++) { + new String("this is just some text to see if we can force gc " + i); + } + // storage will hold weak references until the next JacobObject is + // created + System.gc(); + sizeBeforeGC = ROT.getThreadObjects(false).size(); + debug("Objects left after flood and gc but before adding a new object that clean's up weak references: " + + sizeBeforeGC); + debug("Creating single object. This adds one and causes ROT to clean up GC'd"); + new JacobObject(); + sizeAfterGC = ROT.getThreadObjects(false).size(); + debug("Objects left after adding one (caused weak ref objects to be removed): " + + sizeAfterGC); + new JacobObject(); + if (ROT.getThreadObjects(false).size() != sizeAfterGC + 1) { + debug("Unexpected number of objects after adding only one more " + + ROT.getThreadObjects(false).size()); + } else { + debug("Found number expected after adding one more " + + (sizeAfterGC + 1)); + } + ROT.clearObjects(); + if (ROT.getThreadObjects(false) == null) { + debug("ROT pool was destroyed as expected after clearObjects called."); + } 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); + } } diff --git a/unittest/com/jacob/com/VariantDateTest.java b/unittest/com/jacob/com/VariantDateTest.java index 371c51b..892422f 100644 --- a/unittest/com/jacob/com/VariantDateTest.java +++ b/unittest/com/jacob/com/VariantDateTest.java @@ -7,53 +7,64 @@ import com.jacob.test.BaseTestCase; /** * test cases that should exercise the new date conversion code *

      - * 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. + * 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 VariantDateTest extends BaseTestCase { - public void testVariantDate() { - Date now = new Date(); - Variant holder = new Variant(); - holder.putDate(now); - Date retrievedNow = holder.getJavaDate(); - 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); - Date retrievedNow = holder.getJavaDate(); - retrievedNow = dateVariant.getJavaDate(); - if (!now.equals(retrievedNow)){ - fail("Variant Date Test (1) failed " +now+ " != " +retrievedNow ); - } else { - //System.out.println("Variant Date Test (1) passed"); - } - // verify auto typecasting works - retrievedNow = (Date)dateVariant.toJavaObject(); - if (!now.equals(retrievedNow)){ - fail("Variant Date Test (2) failed " +now+ " != " +retrievedNow ); - } else { - //System.out.println("Variant Date Test (2) 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."); - - } - + /** + * verify the conversion of Variants into java dates + */ + public void testVariantDate() { + Date now = new Date(); + Variant holder = new Variant(); + holder.putDate(now); + Date retrievedNow = holder.getJavaDate(); + if (!now.equals(retrievedNow)) { + fail("Variant Date Test failed " + now + " != " + retrievedNow); + } else { + System.out.println("Variant Date Test passed"); + } + + } + + /** + * verify that the Variant constructor accepts Java dates and converts them + * correctly + */ + public void testVariantDateToJavaObject() { + Date now = new Date(); + Variant holder = new Variant(now); + for (int i = 0; i < 30000; i++) { + Variant dateVariant = new Variant(now); + Date retrievedNow = holder.getJavaDate(); + retrievedNow = dateVariant.getJavaDate(); + if (!now.equals(retrievedNow)) { + fail("Variant Date Test (1) failed " + now + " != " + + retrievedNow); + } else { + // System.out.println("Variant Date Test (1) passed"); + } + // verify auto typecasting works + retrievedNow = (Date) dateVariant.toJavaObject(); + if (!now.equals(retrievedNow)) { + fail("Variant Date Test (2) failed " + now + " != " + + retrievedNow); + } else { + // System.out.println("Variant Date Test (2) 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."); + + } + } diff --git a/unittest/com/jacob/com/VariantTest.java b/unittest/com/jacob/com/VariantTest.java index dd2b3df..ac09e21 100644 --- a/unittest/com/jacob/com/VariantTest.java +++ b/unittest/com/jacob/com/VariantTest.java @@ -1,6 +1,7 @@ package com.jacob.com; import java.math.BigDecimal; +import java.math.BigInteger; import java.util.Date; 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 * *

      - * 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. + * 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 VariantTest extends BaseTestCase { - + /** - * This verifies that toJavaObject() works for all of the - * main data types when they exist as a byRef version. + * This verifies that toJavaObject() works for all of the main data types + * when they exist as a byRef version. *

      - * It compares the toJavaObject() for a byref against the - * toJavaObject() for the regular. - * + * It compares the toJavaObject() for a byref against the toJavaObject() for + * the regular. + * */ - public void testByRefToJavaObject(){ + public void testByRefToJavaObject() { Variant v = null; Variant vByRef = null; - - v = new Variant(new Float(53.3),false); - vByRef = new Variant(new Float(53.3),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 Float(53.3), false); + vByRef = new Variant(new Float(53.3), 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 Double(53.3),false); - vByRef = new Variant(new Double(53.3),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 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(new Double(53.3), false); + vByRef = new Variant(new Double(53.3), 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"); + 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); + 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 // 53.53 had a scale of 64 and 53.52 had a scale of 47 BigDecimal testDecimal = new BigDecimal(53.50); - v = new Variant(testDecimal,false); - vByRef = new Variant(testDecimal,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(testDecimal, false); + vByRef = new Variant(testDecimal, 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"); } Date now = new Date(); - v = new Variant(now,false); - vByRef = new Variant(now,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(now, false); + vByRef = new Variant(now, 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"); } - - // 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 * instead of getDispatch so toString() on dispatch blows up. - * + * */ - public void testDispatchToJavaObject(){ + public void testDispatchToJavaObject() { Variant v2 = new Variant(); v2.putNothing(); // 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 - * + * */ - public void testSomeChangeVT(){ + public void testSomeChangeVT() { 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; v = new Variant(53.3); short originalVT = v.getvt(); short modifier; - + modifier = Variant.VariantShort; vConverted = v.changeType(modifier); - if (vConverted.getvt() != modifier){ - fail("Failed to change Variant "+originalVT - + " using mask "+modifier - + " resulted in "+vConverted.getvt() - ); + if (vConverted.getvt() != modifier) { + fail("Failed to change Variant " + originalVT + " using mask " + + modifier + " resulted in " + vConverted.getvt()); } modifier = Variant.VariantString; vConverted = v.changeType(modifier); - if (vConverted.getvt() != modifier){ - fail("Failed to change Variant "+originalVT - + " using mask "+modifier - + " resulted in "+vConverted.getvt() - ); + if (vConverted.getvt() != modifier) { + fail("Failed to change Variant " + originalVT + " using mask " + + modifier + " resulted in " + vConverted.getvt()); } // can't convert to byref! - modifier = Variant.VariantByref | Variant.VariantShort; + modifier = Variant.VariantByref | Variant.VariantShort; vConverted = v.changeType(modifier); - if (vConverted.getvt() == modifier){ - fail("Should not have been able to change Variant "+originalVT - + " using mask "+modifier - + " resulted in "+vConverted.getvt() - ); + if (vConverted.getvt() == modifier) { + fail("Should not have been able to change Variant " + originalVT + + " using mask " + modifier + " resulted in " + + vConverted.getvt()); } } - + /** * make sure variant with no backing store works. - * + * */ - public void testUninitializedVariant(){ + public void testUninitializedVariant() { Variant v; // Variants created without parameters are auto set to VariantEmpty v = new Variant(); try { - if (v.getvt() == Variant.VariantEmpty){ + if (v.getvt() == Variant.VariantEmpty) { // successful - // System.out.println("Variant initialized without parameters correctly set to empty"); + // System.out.println("Variant initialized without parameters + // correctly set to empty"); } 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){ - throw new RuntimeException("getvt() on uninitialized variant shoud have succeeded, but instead threw exception"); + } catch (IllegalStateException ise) { + throw new RuntimeException( + "getvt() on uninitialized variant shoud have succeeded, but instead threw exception"); } try { v.toString(); - } catch (IllegalStateException ise){ + } catch (IllegalStateException ise) { 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 */ - public void testToStringDoesNotConvert(){ + public void testToStringDoesNotConvert() { Variant v; v = new Variant(true); v.toString(); - if (v.getvt() != Variant.VariantBoolean){ - throw new RuntimeException("toString() converted boolean to something else"); + if (v.getvt() != Variant.VariantBoolean) { + throw new RuntimeException( + "toString() converted boolean to something else"); } else { - //fail("toString() correctly does not convert type"); + // fail("toString() correctly does not convert type"); } - if (v.getBoolean() != true){ - fail("toString() converted boolean true to "+ v.getBoolean()); + if (v.getBoolean() != true) { + fail("toString() converted boolean true to " + v.getBoolean()); } v = new Variant(false); v.toString(); - if (v.getvt() != Variant.VariantBoolean){ - throw new RuntimeException("toString() converted boolean to something else"); + if (v.getvt() != Variant.VariantBoolean) { + throw new RuntimeException( + "toString() converted boolean to something else"); } else { - //fail("toString() correctly does not convert type"); + // fail("toString() correctly does not convert type"); } - if (v.getBoolean() != false){ - fail("toString() converted boolean false to "+ v.getBoolean()); + if (v.getBoolean() != false) { + 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; v = new Variant(true); - //System.out.println("Newly created Variant ("+ v.getBoolean()+") "+ - // "trying to create access violation but it doesn't seem to be easy"); + // System.out.println("Newly created Variant ("+ v.getBoolean()+") "+ + // "trying to create access violation but it doesn't seem to be easy"); v.safeRelease(); try { v.getBoolean(); fail("IllegalStateException should have been thrown when querying safeReleased object"); throw new RuntimeException("test failed"); - } catch (IllegalStateException ise){ - //System.out.println("IllegalStateException correctly thrown after safeRelease"); + } catch (IllegalStateException ise) { + // System.out.println("IllegalStateException correctly thrown after + // safeRelease"); } v = new Variant(true); - for ( int i = 0 ; i < 10; i ++){ - new Variant ("xxx"+i); + for (int i = 0; i < 10; i++) { + new Variant("xxx" + i); new Variant(i); - new Variant ("yyy"+i); + new Variant("yyy" + i); } ComThread.Release(); try { v.getBoolean(); fail("IllegalStateException should have been thrown when querying ComThread.Release"); throw new RuntimeException("test failed"); - } catch (IllegalStateException ise){ - //System.out.println("IllegalStateException correctly thrown after ComThread.Release"); + } catch (IllegalStateException ise) { + // System.out.println("IllegalStateException correctly thrown after + // ComThread.Release"); } } - + /** * verify the constant values aren't released with safeRelease - * + * */ - public void testSafeReleaseConstant(){ - //System.out.println("Using Static constant Variant - should never throw access violation"); + public void testSafeReleaseConstant() { + // System.out.println("Using Static constant Variant - should never + // throw access violation"); Variant.VT_TRUE.safeRelease(); - if (Variant.VT_TRUE.getBoolean() != true){ + if (Variant.VT_TRUE.getBoolean() != true) { fail("VT_TRUE has been broken by SafeRelease()"); throw new RuntimeException("test failed"); } else { - //System.out.println("VT_TRUE survived SafeRelease()"); + // System.out.println("VT_TRUE survived SafeRelease()"); } - - for ( int i = 0 ; i < 10; i ++){ - new Variant ("xxx"+i); + + for (int i = 0; i < 10; i++) { + new Variant("xxx" + i); new Variant(i); - new Variant ("yyy"+i); + new Variant("yyy" + i); } ComThread.Release(); - - if (Variant.VT_TRUE.getBoolean() != true){ + + if (Variant.VT_TRUE.getBoolean() != true) { fail("VT_TRUE has been broken by ComThread.Release()"); throw new RuntimeException("test failed"); } 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 - * didn't work and now the methods on the Variant are smarter about - * working after a release - * + * this used to try and and create an access violation but that didn't work + * and now the methods on the Variant are smarter about working after a + * release + * */ - public void testSafeReleaseString(){ - String mTestString = "Guitar Hero"; + public void testSafeReleaseString() { + String mTestString = "Guitar Hero"; Variant v = new Variant(mTestString); - //System.out.println("Newly created Variant ("+ v.getString()+") "+ - // "about to safe release and then access"); + // System.out.println("Newly created Variant ("+ v.getString()+") "+ + // "about to safe release and then access"); v.safeRelease(); try { v.getString(); fail("IllegalStateException should have been thrown when querying safeReleased object"); throw new RuntimeException("test failed"); - } catch (IllegalStateException ise){ - //System.out.println("IllegalStateException correctly thrown after safeRelease"); + } catch (IllegalStateException ise) { + // System.out.println("IllegalStateException correctly thrown after + // safeRelease"); } - } - - /** - * verifies objectIsAConstant works as expected - * - */ - public void testObjectIsAConstant(){ - Variant v = new Variant("d"); - if (!v.objectIsAConstant(Variant.VT_FALSE)){ - fail("did not recognize VT_FALSE"); - } - if (!v.objectIsAConstant(Variant.VT_TRUE)){ - fail("did not recognize VT_TRUE"); - } - if (!v.objectIsAConstant(Variant.VT_MISSING)){ - fail("did not recognize VT_MISSING"); - } - if (!v.objectIsAConstant(Variant.DEFAULT)){ - fail("did not recognize DEFAULT"); - } - if (v.objectIsAConstant(new Variant(true))){ - fail("confused a boolean with VT_TRUE"); - } - if (v.objectIsAConstant(new Variant(false))){ - fail("confused a boolean with VT_FALSE"); - } - - - } - + } + + /** + * verifies objectIsAConstant works as expected + * + */ + public void testObjectIsAConstant() { + Variant v = new Variant("d"); + if (!v.objectIsAConstant(Variant.VT_FALSE)) { + fail("did not recognize VT_FALSE"); + } + if (!v.objectIsAConstant(Variant.VT_TRUE)) { + fail("did not recognize VT_TRUE"); + } + if (!v.objectIsAConstant(Variant.VT_MISSING)) { + fail("did not recognize VT_MISSING"); + } + if (!v.objectIsAConstant(Variant.DEFAULT)) { + fail("did not recognize DEFAULT"); + } + if (v.objectIsAConstant(new Variant(true))) { + fail("confused a boolean with VT_TRUE"); + } + if (v.objectIsAConstant(new Variant(false))) { + fail("confused a boolean with VT_FALSE"); + } + + } + /** * tests put and get methods looking for obvious defects - * + * */ - public void testPutsAndGets(){ + public void testPutsAndGets() { Variant v = new Variant(); - v.putInt((int)10); - assertEquals("int test failed", (int)10, v.getInt()); + v.putInt(10); + assertEquals("int test failed", 10, v.getInt()); - v.putShort((short)20); - assertEquals("short test failed", (short)20, v.getShort()); - - v.putByte((byte)30); - assertEquals("byte test failed", (byte)30, v.getByte()); + v.putShort((short) 20); + assertEquals("short test failed", (short) 20, v.getShort()); + + v.putByte((byte) 30); + assertEquals("byte test failed", (byte) 30, v.getByte()); v.putFloat(40); - if (v.getFloat() != 40.0){ + if (v.getFloat() != 40.0) { fail("float test failed"); } v.putDouble(50); - if (v.getDouble() != 50.0){ + if (v.getDouble() != 50.0) { fail("double test failed"); } - + v.putString("1234.567"); - assertEquals("string test failed","1234.567", v.getString()); + assertEquals("string test failed", "1234.567", v.getString()); v.putBoolean(true); - assertEquals("failed boolean test(true)",true, v.getBoolean()); + assertEquals("failed boolean test(true)", true, v.getBoolean()); 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"); v.putDecimal(testDecimal); - assertEquals("failed BigDecimal test", testDecimal,v.getDecimal()); - - + assertEquals("failed BigDecimal test", testDecimal, v.getDecimal()); + Date ourDate = new Date(); v.putDate(ourDate); Date retrievedDate = v.getJavaDate(); - if (!retrievedDate.equals(ourDate)){ + if (!retrievedDate.equals(ourDate)) { fail("failed java date load and unload"); } - + v.putNull(); - if (!v.isNull()){ + if (!v.isNull()) { fail("failed detecting set null"); } v.putString("something other than null"); - if (v.isNull()){ + if (v.isNull()) { fail("failed null replacement with string"); } - + v.putEmpty(); - if (!v.isNull()){ + if (!v.isNull()) { fail("failed detecting set empty as null"); } v.putString("something other than null"); - if (v.isNull()){ + if (v.isNull()) { fail("failed empty replacement with string as isNull"); } Variant v2 = new Variant(); v2.putNothing(); - if (v2.getvt() != Variant.VariantDispatch){ + if (v2.getvt() != Variant.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"); } // 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"); } - + } /** - * 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 - * + * verify decimal works right */ - public void testManyThreadedInit(){ - VariantInitTestThread threads[] = new VariantInitTestThread[75]; - - System.out.println("Starting thread test ("+threads.length + public void testDecimalConversion() { + Variant v = new Variant(); + v.changeType(Variant.VariantDecimal); + for (int i = 10; i >= -10; i--) { + v.putDecimal(new BigDecimal(i)); + // first see if we can get it back as decimal + assertEquals("conversion back to decimal failed " + i, + new BigDecimal(i), v.getDecimal()); + v.changeType(Variant.VariantFloat); + // now see if a float conversion would work + assertEquals("conversion to float failed " + i, new Float(i), v + .getFloat()); + // now convert it back to decimal for reassignment + v.changeType(Variant.VariantDecimal); + assertTrue("Failed conversion of type back to Decimal " + i, v + .getvt() == Variant.VariantDecimal); + } + + } + + /** + * for(BigDecimal i in 79228162514264337593543950330.0 .. + * 79228162514264337593543950341.0) { com.jacob.com.Variant dv = new + * com.jacob.com.Variant(i, false) println i + " : " + dv.getDecimal() } + * + */ + public void testLargeDecimals() { + // the largest decimal number, not in hex is + // 7922816251426433759354395033.0 + BigInteger theStartDigits = new BigInteger("ffffffffffffffffffffff00", + 16); + BigInteger theMaxDigits = new BigInteger("ffffffffffffffffffffffff", 16); + BigDecimal startDecimal = new BigDecimal(theStartDigits); + BigDecimal endDecimal = new BigDecimal(theMaxDigits); + BigDecimal incrementDecimal = new BigDecimal(1); + BigDecimal testDecimal = startDecimal; + Variant testVariant; + while (endDecimal.compareTo(testDecimal) >= 0) { + testVariant = new Variant(testDecimal, false); + BigDecimal result = testVariant.getDecimal(); + assertEquals(testDecimal, result); + testDecimal = testDecimal.add(incrementDecimal); + } + // test Decimal is now too large + try { + new Variant(testDecimal, false); + } catch (IllegalArgumentException iae) { + // System.out.println("Caught expected exception"); + } + // lets try something different. we can call putVariant with rounding + // enabled + testVariant = new Variant(); + testVariant.changeType(Variant.VariantDecimal); + try { + testVariant.putDecimal(endDecimal.setScale(30)); + fail("Should have thrown exception with scale of 30 and no rounding"); + } catch (IllegalArgumentException iae) { + // should have caught this exception + } + // now we test with a negative scale. Note that you can't do with + // without some magic, in this case scientific notation + try { + testVariant.putDecimal(new BigDecimal("700E24")); + assertTrue(new BigDecimal("700E24").compareTo(testVariant + .getDecimal()) == 0); + } catch (IllegalArgumentException iae) { + // should have caught this exception + } + + testVariant.putDecimal(VariantUtilities + .roundToMSDecimal(new BigDecimal("700E24"))); + // use compareTo because it takes into account varying scales + assertTrue(new BigDecimal("700E24").compareTo(testVariant.getDecimal()) == 0); + + // This passes because the number is within range. + testVariant.putDecimal(endDecimal); + + // this should pass because we have rounding turned on + // it turns out the max number gets more digits when + // it's scale is set to 30. so we can't use the max number when there is + // a scale + BigDecimal modifiedDecimal = endDecimal; + System.out.println("integer piece starts as " + + modifiedDecimal.unscaledValue().toString(16) + " scale=: " + + modifiedDecimal.scale()); + System.out.println("integer piece after rounding without scale is " + + VariantUtilities.roundToMSDecimal(modifiedDecimal) + .unscaledValue().toString(16) + " scale=: " + + modifiedDecimal.scale()); + System.out.println("integer piece after rounding with scale 30 is " + + VariantUtilities.roundToMSDecimal( + modifiedDecimal.setScale(30)).unscaledValue().toString( + 16) + " scale=: " + modifiedDecimal.scale()); + try { + testVariant.putDecimal(VariantUtilities + .roundToMSDecimal(modifiedDecimal.setScale(30))); + fail("should have thrown an exception for a number whose scale " + + "change created too many digits to be represented."); + } catch (IllegalArgumentException iae) { + // should catch an exception here because the rounding after scale + // change would have made the number too large + } + + System.out.println(""); + modifiedDecimal = endDecimal.subtract(incrementDecimal); + System.out.println("integer piece starts as " + + modifiedDecimal.unscaledValue().toString(16) + " scale=: " + + modifiedDecimal.scale()); + System.out.println("integer piece after rounding without scale is " + + VariantUtilities.roundToMSDecimal(modifiedDecimal) + .unscaledValue().toString(16) + " scale=: " + + modifiedDecimal.scale()); + System.out.println("integer piece after rounding with scale 30 is " + + VariantUtilities.roundToMSDecimal( + modifiedDecimal.setScale(30)).unscaledValue().toString( + 16) + " scale=: " + modifiedDecimal.scale()); + testVariant.putDecimal(VariantUtilities + .roundToMSDecimal(modifiedDecimal.setScale(30))); + System.out.println(""); + } + + /** + * Spin up a lot of threads and have them all create variants 3/2007 there + * have been several reports in multi-threaded servers that show init() + * failing + * + */ + public void testManyThreadedInit() { + VariantInitTestThread threads[] = new VariantInitTestThread[75]; + + System.out.println("Starting thread test (" + threads.length + " threads each creating 10000 objects)." + " This may take 30 seconds or more."); - for (int i = 0; i < threads.length; i++) - { - threads[i] = new VariantInitTestThread("thread-" + i, 10000); - } - for (int i = 0; i < threads.length; i++) - { - threads[i].start(); - } - int numComplete = 0; - while (numComplete < threads.length){ - // give the works time to work - try { - Thread.sleep(333); - } catch (InterruptedException ie){ + for (int i = 0; i < threads.length; i++) { + threads[i] = new VariantInitTestThread("thread-" + i, 10000); + } + for (int i = 0; i < threads.length; i++) { + threads[i].start(); + } + int numComplete = 0; + while (numComplete < threads.length) { + // give the works time to work + try { + Thread.sleep(333); + } catch (InterruptedException ie) { // do nothing } - numComplete = 0; - for ( int i = 0; i < threads.length; i++){ - if (threads[i].isComplete){ - numComplete++; - } - } - //System.out.print("["+numComplete+"/"+threads.length+"]"); - } + numComplete = 0; + for (int i = 0; i < threads.length; i++) { + if (threads[i].isComplete) { + numComplete++; + } + } + // System.out.print("["+numComplete+"/"+threads.length+"]"); + } 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; - } - /** - * 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){ + /** + * a class to create variants in separate threads + * + */ + class VariantInitTestThread extends Thread { + private boolean isComplete = false; + + private int initialRunSize = 0; + + /** + * @param newThreadName + * the name for the thread + * @param iStartCount + * number of threads to start with + */ + 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 } - //System.out.println(Thread.currentThread().getName()); - Variant testSubject = new Variant(variantIndex); - testSubject.getvt(); - testSubject.getInt(); - } - isComplete = true; - } + // System.out.println(Thread.currentThread().getName()); + Variant testSubject = new Variant(variantIndex); + testSubject.getvt(); + testSubject.getInt(); + } + isComplete = true; + } } } diff --git a/unittest/com/jacob/com/VariantUtilitiesTest.java b/unittest/com/jacob/com/VariantUtilitiesTest.java new file mode 100644 index 0000000..746cbaa --- /dev/null +++ b/unittest/com/jacob/com/VariantUtilitiesTest.java @@ -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); + + } +} diff --git a/unittest/com/jacob/test/BaseTestCase.java b/unittest/com/jacob/test/BaseTestCase.java index cbd2cd7..d545146 100644 --- a/unittest/com/jacob/test/BaseTestCase.java +++ b/unittest/com/jacob/test/BaseTestCase.java @@ -7,6 +7,9 @@ import junit.framework.TestCase; 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 * Eclipse). Look in the docs area at the Jacob usage document for command line * options. Or try these: @@ -35,10 +38,11 @@ public class BaseTestCase extends TestCase { /** * this test exists just to test the setup. */ - public void testSetup(){ + public void testSetup() { JacobObject foo = new JacobObject(); assertNotNull(foo); } + /** * * @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. - * Used to derive the path to a resouce in the file system - * where the resource is co-located with the referenced class. + * Converts the class name into a path and appends the resource name. Used + * to derive the path to a resource in the file system where the resource is + * co-located with the referenced class. * * @param resourceName * @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) { String classPackageName = classInSamePackageAsResource.getName(); @@ -65,14 +71,15 @@ public class BaseTestCase extends TestCase { if (i == -1) { classPackageName = ""; } 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('.', '^'); System.out.println("classPackageName: " + classPackageName); String fullPathToResource; - if (classPackageName.length()> 0){ + if (classPackageName.length() > 0) { fullPathToResource = classPackageName + "^" + resourceName; } else { fullPathToResource = resourceName; @@ -81,30 +88,35 @@ public class BaseTestCase extends TestCase { fullPathToResource = fullPathToResource.replace('^', '/'); System.out.println("fullPathToResource: " + fullPathToResource); - URL urlToLibrary = - classInSamePackageAsResource.getClassLoader().getResource(fullPathToResource); - assertNotNull("URL to resource "+resourceName+" should not be null",urlToLibrary); + URL urlToLibrary = classInSamePackageAsResource.getClassLoader() + .getResource(fullPathToResource); + 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(); - System.out.println("url to library: "+urlToLibrary); - System.out.println("fullPathToResourceAsFile: "+fullPathToResourceAsFile); + System.out.println("url to library: " + urlToLibrary); + System.out.println("fullPathToResourceAsFile: " + + fullPathToResourceAsFile); return fullPathToResourceAsFile; } /** - * Converts the class name into a path and appends the resource name. - * Used to derive the path to a resouce in the file system - * where the resource is co-located with the referenced class. + * Converts the class name into a path and appends the resource name. Used + * to derive the path to a resource in the file system where the resource is + * co-located with the referenced class. * * @param resourceName * @param classInSamePackageAsResource - * @return returns the path in the file system of the requested resource in windows c - * compatible format + * @return returns the path in the file system of the requested resource in + * windows c compatible format */ - public String getWindowsFilePathToPackageResource( - String resourceName, Class classInSamePackageAsResource) { - String javaFilePath = getJavaFilePathToPackageResource( - resourceName, classInSamePackageAsResource); + @SuppressWarnings("unchecked") + public String getWindowsFilePathToPackageResource(String resourceName, + Class classInSamePackageAsResource) { + String javaFilePath = getJavaFilePathToPackageResource(resourceName, + classInSamePackageAsResource); javaFilePath = javaFilePath.replace('/', '\\'); return javaFilePath.substring(1); } @@ -115,10 +127,11 @@ public class BaseTestCase extends TestCase { * @param classInSamePackageAsResource * @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) { - String fullPathToResource = getJavaFilePathToPackageResource(resourceName, - classInSamePackageAsResource); + String fullPathToResource = getJavaFilePathToPackageResource( + resourceName, classInSamePackageAsResource); ClassLoader localClassLoader = classInSamePackageAsResource .getClassLoader(); 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 - * loaded from. + * load a library from same place in the file system that the class was + * loaded from. *

      - * This is an attempt to let unit tests run without having to run - * regsvr32. + * This is an attempt to let unit tests run without having to run regsvr32. * * @param libraryName * @param classInSamePackageAsResource */ - public void loadLibraryFromClassPackage(String libraryName, + @SuppressWarnings( { "unchecked", "unused" }) + private void loadLibraryFromClassPackage(String libraryName, Class classInSamePackageAsResource) { String libraryNameWithSuffix = ""; String fullLibraryNameWithPath = ""; @@ -149,12 +162,13 @@ public class BaseTestCase extends TestCase { } else { 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( libraryNameWithSuffix, classInSamePackageAsResource); System.load(fullLibraryNameWithPath); // requires that the dll be on the library path - //System.loadLibrary(fullLibraryNameWithPath); + // System.loadLibrary(fullLibraryNameWithPath); } } diff --git a/unittest/com/jacob/test/errors/UnicodeErrorTest.java b/unittest/com/jacob/test/errors/UnicodeErrorTest.java index d6f60a7..b4a4f1c 100644 --- a/unittest/com/jacob/test/errors/UnicodeErrorTest.java +++ b/unittest/com/jacob/test/errors/UnicodeErrorTest.java @@ -5,24 +5,30 @@ import com.jacob.activeX.ActiveXComponent; import com.jacob.com.ComException; /** - * This test verifies patch SF 1794811 . - * It shows how unicode filenames throw exceptions in 1.13M4 and earlier. + * This test verifies patch SF 1794811 . It shows how unicode filenames throw + * exceptions in 1.13M4 and earlier. + * * @author justme84 - * + * */ 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() { ActiveXComponent application = new ActiveXComponent("Word.Application"); - ActiveXComponent documents = application.getPropertyAsComponent("Documents"); + ActiveXComponent documents = application + .getPropertyAsComponent("Documents"); String fileName = "abc\u0411\u0412\u0413\u0414def"; try { documents.invoke("Open", fileName); fail("Should have thrown an exception"); } catch (ComException e) { - assertTrue("Error message should contain file name with unicode " + - "characters in it. "+e.getMessage(), - e.getMessage().indexOf(fileName) > 0); + assertTrue("Error message should contain file name with unicode " + + "characters in it. " + e.getMessage(), e.getMessage() + .indexOf(fileName) > 0); } } } \ No newline at end of file diff --git a/unittest/com/jacob/test/events/ExcelEventTest.java b/unittest/com/jacob/test/events/ExcelEventTest.java index 24fcd10..b076c29 100644 --- a/unittest/com/jacob/test/events/ExcelEventTest.java +++ b/unittest/com/jacob/test/events/ExcelEventTest.java @@ -2,6 +2,7 @@ package com.jacob.test.events; 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.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 - * Excel events (added post 1.9.1 Eclipse Settings.) This also uses the 1.9.1 - * InvocationProxy to receive the events. + * Excel events (added post 1.9.1 Eclipse Settings.) This also uses the 1.9.1 + * 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 *

      - * 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. + * 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 ExcelEventTest extends BaseTestCase { /** * load up excel, register for events and make stuff happen + * * @param args */ 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"; // Grab The Component. - ActiveXComponent axc = new ActiveXComponent(pid); - try { - // 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); + ActiveXComponent axc = new ActiveXComponent(excelApplicationProgramId); + hookupListener(axc, excelApplicationProgramId, typeLibLocation); - } + try { System.out.println("version=" + axc.getProperty("Version")); System.out.println("version=" + Dispatch.get(axc, "Version")); @@ -52,6 +46,7 @@ public class ExcelEventTest extends BaseTestCase { Dispatch workbooks = axc.getPropertyAsComponent("Workbooks"); Dispatch workbook = Dispatch.get(workbooks, "Add").toDispatch(); Dispatch sheet = Dispatch.get(workbook, "ActiveSheet").toDispatch(); + hookupListener(sheet, excelSheetProgramId, typeLibLocation); Dispatch a1 = Dispatch.invoke(sheet, "Range", Dispatch.Get, new Object[] { "A1" }, new int[1]).toDispatch(); 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"); Dispatch.put(a1, "Value", "123.456"); Dispatch.put(a2, "Formula", "=A1*2"); - System.out.println("Retrieved a1 from excel:" + Dispatch.get(a1, "Value")); - System.out.println("Retrieved a2 from excel:" + Dispatch.get(a2, "Value")); + System.out.println("Retrieved a1 from excel:" + + Dispatch.get(a1, "Value")); + System.out.println("Retrieved a2 from excel:" + + Dispatch.get(a2, "Value")); Variant f = new Variant(false); Dispatch.call(workbook, "Close", f); axc.invoke("Quit", new Variant[] {}); } catch (ComException cfe) { cfe.printStackTrace(); - fail("Failed to attach to " + pid + ": " + fail("Failed to attach to " + excelApplicationProgramId + ": " + 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 { - /** - * 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; - } + private String listenerPrefix = "-"; -} + /** + * 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; + } + + } } diff --git a/unittest/com/jacob/test/events/IETest.java b/unittest/com/jacob/test/events/IETest.java index cf564e0..c3d4230 100644 --- a/unittest/com/jacob/test/events/IETest.java +++ b/unittest/com/jacob/test/events/IETest.java @@ -6,212 +6,406 @@ import com.jacob.com.Dispatch; import com.jacob.com.DispatchEvents; import com.jacob.com.Variant; import com.jacob.test.BaseTestCase; + /** * This test runs fine against jdk 1.4 and 1.5 * - * This demonstrates the new event handling code in jacob 1.7 - * This example will open up IE and print out some of the events - * it listens to as it havigates to web sites. - * contributed by Niels Olof Bouvin mailto:n.o.bouvin@daimi.au.dk - * and Henning Jae jehoej@daimi.au.dk + * This demonstrates the new event handling code in jacob 1.7 This example will + * open up IE and print out some of the events it listens to as it havigates to + * web sites. contributed by Niels Olof Bouvin mailto:n.o.bouvin@daimi.au.dk and + * Henning Jae jehoej@daimi.au.dk *

      - * 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. + * 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 IETest extends BaseTestCase { - + + /** + * runs the IE test and feeds it commands + */ public void testRunIE() { - // this line starts the pump but it runs fine without it - ComThread.startMainSTA(); - // remove this line and it dies - ///ComThread.InitMTA(true); - IETestThread aThread = new IETestThread(); - aThread.start(); - while (aThread.isAlive()){ - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - // doen with the sleep - //e.printStackTrace(); - } - } - System.out.println("Main: Thread quit, about to quit main sta in thread " - +Thread.currentThread().getName()); - // this line only does someting if startMainSTA() was called - 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); - } - } + // this line starts the pump but it runs fine without it + ComThread.startMainSTA(); + // remove this line and it dies + // /ComThread.InitMTA(true); + IETestThread aThread = new IETestThread(); + aThread.start(); + while (aThread.isAlive()) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + // doen with the sleep + // e.printStackTrace(); + } + } + System.out + .println("Main: Thread quit, about to quit main sta in thread " + + Thread.currentThread().getName()); + // this line only does someting if startMainSTA() was called + 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 IETestThread extends Thread -{ +class IETestThread extends Thread { + /** flag that says we got a quit message from IE */ public static boolean quitHandled = false; - + /** * holds any caught exception so the main/test case can see them */ 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(); + } -/** - * 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 -{ - public void BeforeNavigate2(Variant[] args) { - System.out.println("IEEvents Received ("+Thread.currentThread().getName()+"): BeforeNavigate2 "+args.length); - } + 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")); - public void CommandStateChange(Variant[] args) { - System.out.println("IEEvents Received ("+Thread.currentThread().getName()+"): CommandStateChange "+args.length); - } + 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(); - public void DocumentComplete(Variant[] args) { - System.out.println("IEEvents Received ("+Thread.currentThread().getName()+"): DocumentComplete "+args.length); - } + 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()); - public void DownloadBegin(Variant[] args) { - System.out.println("IEEvents Received ("+Thread.currentThread().getName()+"): DownloadBegin "+args.length); - } + ComThread.Release(); + } - 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); - IETestThread.quitHandled = true; - } + /** + * Internet explorer event this proxy can receive + * + * @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); + } + } } diff --git a/unittest/com/jacob/test/events/IETestActiveXProxy.java b/unittest/com/jacob/test/events/IETestActiveXProxy.java index 7993189..9f45862 100644 --- a/unittest/com/jacob/test/events/IETestActiveXProxy.java +++ b/unittest/com/jacob/test/events/IETestActiveXProxy.java @@ -6,213 +6,284 @@ import com.jacob.com.ComThread; import com.jacob.com.Dispatch; import com.jacob.com.Variant; import com.jacob.test.BaseTestCase; + /** * This test runs fine against jdk 1.4 and 1.5 * - * This demonstrates the new event handling code in jacob 1.7 - * This example will open up IE and print out some of the events - * it listens to as it havigates to web sites. - * contributed by Niels Olof Bouvin mailto:n.o.bouvin@daimi.au.dk - * and Henning Jae jehoej@daimi.au.dk + * This demonstrates the new event handling code in jacob 1.7 This example will + * open up IE and print out some of the events it listens to as it havigates to + * web sites. contributed by Niels Olof Bouvin mailto:n.o.bouvin@daimi.au.dk and + * Henning Jae jehoej@daimi.au.dk *

      - * 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. + * 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 IETestActiveXProxy extends BaseTestCase { - - public void testIEActiveProxyCallback() { - // this line starts the pump but it runs fine without it - ComThread.startMainSTA(); - // remove this line and it dies - ///ComThread.InitMTA(true); - IETestActiveProxyThread aThread = new IETestActiveProxyThread(); - aThread.start(); - while (aThread.isAlive()){ - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - // doen with the sleep - //e.printStackTrace(); - } - } - System.out.println("Main: Thread quit, about to quit main sta in thread " - +Thread.currentThread().getName()); - // this line only does someting if startMainSTA() was called - 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); - } - } + /** + * the main test method that builds up the connection and runs the test + */ + public void testIEActiveProxyCallback() { + // this line starts the pump but it runs fine without it + ComThread.startMainSTA(); + // remove this line and it dies + // /ComThread.InitMTA(true); + IETestActiveProxyThread aThread = new IETestActiveProxyThread(); + aThread.start(); + while (aThread.isAlive()) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + // doen with the sleep + // e.printStackTrace(); + } + } + System.out + .println("Main: Thread quit, about to quit main sta in thread " + + Thread.currentThread().getName()); + // this line only does someting if startMainSTA() was called + 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; - + /** * holds any caught exception so the main/test case can see them */ 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(); + } -/** - * 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 BeforeNavigate2(Dispatch pDisp, String url, Integer flags, - String targetFrameName, Variant postData, String headers, Boolean cancel) { - System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): BeforeNavigate2 "+url); - } + 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")); - public void CommandStateChange(Integer command, Boolean enable) { - System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): CommandStateChange "+command); - } + 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(); - public void DocumentComplete(Dispatch pDisp, String url) { - System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): DocumentComplete "+url); - } + 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()); - public void DownloadBegin() { - System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): DownloadBegin "); - } + ComThread.Release(); + } - 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) { - System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): NavigateComplete "+url); - } + public void BeforeNavigate2(Dispatch pDisp, String url, Integer flags, + 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) { - System.out.println("IEEvents Received ("+Thread.currentThread().getName()+"): NavigateError "+statusCode); - } + public void CommandStateChange(Integer command, Boolean enable) { + System.out.println("IEEventsActiveProxy Received (" + + Thread.currentThread().getName() + + "): CommandStateChange " + command); + } - public void NewWindow2(Dispatch pDisp, Boolean cancel) { - System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): NewWindow2 "+pDisp); - } + public void DocumentComplete(Dispatch pDisp, String url) { + System.out.println("IEEventsActiveProxy Received (" + + Thread.currentThread().getName() + "): DocumentComplete " + + url); + } - public void OnFullScreen(Boolean fullScreen) { - System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): OnFullScreen "+fullScreen); - } + public void DownloadBegin() { + System.out.println("IEEventsActiveProxy Received (" + + Thread.currentThread().getName() + "): DownloadBegin "); + } - public void OnMenuBar(Boolean menuBar) { - System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): OnMenuBar "+menuBar); - } + public void DownloadComplete() { + System.out + .println("IEEventsActiveProxy Received (" + + Thread.currentThread().getName() + + "): DownloadComplete "); + } - public void OnQuit() { - System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): OnQuit "); - IETestActiveProxyThread.quitHandled = true; - } + public void NavigateComplete2(Dispatch pDisp, String url) { + System.out.println("IEEventsActiveProxy Received (" + + Thread.currentThread().getName() + "): NavigateComplete " + + url); + } - public void OnStatusBar(Boolean statusBar) { - System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): OnStatusBar "+statusBar); - } + public void NavigateError(Dispatch pDispatch, String url, + String targetFrameName, Integer statusCode, Boolean Cancel) { + System.out.println("IEEvents Received (" + + Thread.currentThread().getName() + "): NavigateError " + + statusCode); + } - public void OnTheaterMode(Boolean theaterMode) { - System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): OnTheaterMode "+theaterMode); - } + public void NewWindow2(Dispatch pDisp, Boolean cancel) { + System.out.println("IEEventsActiveProxy Received (" + + Thread.currentThread().getName() + "): NewWindow2 " + + pDisp); + } - public void OnToolBar(Boolean onToolBar) { - System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): OnToolBar "+onToolBar); - } + public void OnFullScreen(Boolean fullScreen) { + System.out.println("IEEventsActiveProxy Received (" + + Thread.currentThread().getName() + "): OnFullScreen " + + fullScreen); + } - public void OnVisible(Boolean onVisible) { - System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): onVisible "+ onVisible); - } + public void OnMenuBar(Boolean menuBar) { + System.out.println("IEEventsActiveProxy Received (" + + Thread.currentThread().getName() + "): OnMenuBar " + + menuBar); + } - public void ProgressChange() { - System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): ProgressChange "); - } + public void OnQuit() { + System.out.println("IEEventsActiveProxy Received (" + + Thread.currentThread().getName() + "): OnQuit "); + IETestActiveProxyThread.quitHandled = true; + } - public void PropertyChange() { - System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): PropertyChange "); - } + public void OnStatusBar(Boolean statusBar) { + System.out.println("IEEventsActiveProxy Received (" + + Thread.currentThread().getName() + "): OnStatusBar " + + statusBar); + } - public void SetSecureLockIcon(Integer secureLockIcon) { - System.out.println("IEEvents Received ("+Thread.currentThread().getName()+"): setSecureLockIcon "+secureLockIcon); - } + public void OnTheaterMode(Boolean theaterMode) { + System.out.println("IEEventsActiveProxy Received (" + + Thread.currentThread().getName() + "): OnTheaterMode " + + theaterMode); + } - public void StatusTextChange() { - System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): StatusTextChange "); - } + public void OnToolBar(Boolean onToolBar) { + System.out.println("IEEventsActiveProxy Received (" + + Thread.currentThread().getName() + "): OnToolBar " + + onToolBar); + } - public void TitleChange() { - System.out.println("IEEventsActiveProxy Received ("+Thread.currentThread().getName()+"): TitleChange "); - } + public void OnVisible(Boolean onVisible) { + System.out.println("IEEventsActiveProxy Received (" + + Thread.currentThread().getName() + "): onVisible " + + onVisible); + } - public void WindowClosing(Boolean isChildWindow) { - System.out.println("IEEvents Received ("+Thread.currentThread().getName()+"): WindowClosing "+isChildWindow); - } -} + public void ProgressChange() { + 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); + } + } } diff --git a/unittest/com/jacob/test/events/WordEventTest.java b/unittest/com/jacob/test/events/WordEventTest.java index 84f82c1..bc81b73 100644 --- a/unittest/com/jacob/test/events/WordEventTest.java +++ b/unittest/com/jacob/test/events/WordEventTest.java @@ -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 - * Excel events (added post 1.9.1 Eclipse Settings.) - * That test was modified make this a MSWord event listener to demonstrate - * that the InvocationProxy code works with MS Word Events - * This also uses the 1.10 - * InvocationProxy to receive the events. + * Excel events (added post 1.9.1 Eclipse Settings.) That test was modified make + * this a MSWord event listener to demonstrate that the InvocationProxy code + * works with MS Word Events This also uses the 1.10 InvocationProxy to receive + * the events. *

      - * 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. + * 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 WordEventTest extends BaseTestCase { /** * load up word, register for events and make stuff happen + * * @param args */ public void testCaptureWordEvents() { @@ -49,38 +50,44 @@ public class WordEventTest extends BaseTestCase { // this is different from the ExcelEventTest because it uses // the jacob active X api instead of the Dispatch api System.out.println("version=" + axc.getPropertyAsString("Version")); - axc.setProperty("Visible",true); - ActiveXComponent documents = axc.getPropertyAsComponent("Documents"); - if (documents == null){ + axc.setProperty("Visible", true); + ActiveXComponent documents = axc + .getPropertyAsComponent("Documents"); + if (documents == null) { fail("unable to get documents"); } axc.invoke("Quit", new Variant[] {}); } catch (ComException cfe) { cfe.printStackTrace(); - fail("Failed to attach to " + pid + ": " + cfe.getMessage()); + fail("Failed to attach to " + pid + ": " + cfe.getMessage()); } - System.out.println( - "Someone needs to add some MSWord commands to this to " + - "make some on screen stuff happens so the tester " + - "thinks we tested something"); - } - -public class WordEvents extends InvocationProxy { - /** - * Constructor so we can create an instance that implements invoke() - */ - public WordEvents() { + System.out + .println("Someone needs to add some MSWord commands to this to " + + "make some on screen stuff happens so the tester " + + "thinks we tested something"); } /** - * 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[]) { - System.out.println("Received event from Windows program" + methodName); - return null; - } + 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 + */ + public Variant invoke(String methodName, Variant targetParameter[]) { + System.out.println("Received event from Windows program" + + methodName); + return null; + } + + } } \ No newline at end of file diff --git a/unittest/com/jacob/test/excel/ControllerTest.java b/unittest/com/jacob/test/excel/ControllerTest.java new file mode 100644 index 0000000..efd6d4b --- /dev/null +++ b/unittest/com/jacob/test/excel/ControllerTest.java @@ -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 list = controller.getColumnA(super + .getWindowsFilePathToPackageResource("teste.xls", this + .getClass())); + assertEquals(50, list.size()); + } + + public void testGetColumnB() { + List 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 columnA; + + private List columnB; + + public List getColumnA(String pathToTest) { + load(pathToTest); + return columnA; + } + + public List 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á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ão. O + * valor é escrito configurando a propriedade Value da célula + * + * @param celula - + * célula para escrever novo valor + * @param sheet - + * pasta da planilha em questã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údo + * da propriedade Value da célula + * + * @param celula - + * célula a ser lida + * @param sheet - + * pasta da planilha que contém a célula + * @return - conteú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ência para a célua ou conjunto de células especificado no + * parametro + * + * @param celula - + * Referê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ém as células + * @return - referencia para um célula ou conjunto de células, + * dependendo do parâ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ência para conjunto de células + * @param sheet - + * Pasta que contém as cálulas referenciadas + * @return - Lista onde cada elemento é o valor de uma célula + * referenciada na conjunto + */ + public List obterValoresRange(String celulas, Dispatch sheet) { + List valores = new LinkedList(); + + // obtem valor das celulas como um Variant + Variant var = obterValorCelula(celulas, sheet); + + // toString da Variant é 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ção de ação a ser executada em planilha excel. + * + * @param xl - + * Referencia para aplicaçã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()"); + } + } +} diff --git a/unittest/com/jacob/test/excel/teste.xls b/unittest/com/jacob/test/excel/teste.xls new file mode 100644 index 0000000000000000000000000000000000000000..e039eef3d89fc6f5bb5327a0697d36fd33ec6f23 GIT binary patch literal 15360 zcmeI3cT^P5md6_ya?W``a*_;66c8jxmLxfgq#-9k0Y{QVK~X@02!coy5R|B(M3E#C zBuNyJ3`*QC-uu1t+jn-~`R)5_chA(Ed#meHHC;X5?jG)~9zOL^PUlrJ%|QQD6d@ew z_=FI``xD24w^{yZQ$TS4$q8uwQ8UBaFv67oLkbWQz$X$97aCye#qVr^H*p|H1d@iZ zPG83Nnmugp#GWmUjACoayjWxEqOezi4xiZxJD;P$IS>;qdoNSM>%K>eW!6ea(zo&% z2pg(Ew8GxIV-~&|EFmu_;@J^@yO6d*dGdaR95oL1_SWUxJ3gi?e2!D32ZaUmbgMb! zBIe&zcRrl(N0+jVyRk}TX`wlDN{Dd~)K32F-xUn3)VRjf%<1a3W`iuwA)o28w>BbU$F99eMB zvLqwy1G%VR-*ik3dvE=6c&r4X0rom03J?{vUN3}qSQi|Wp6luya^hy$;Hw0W3!6!R zJxZGc_LfUzuy>$)1-}PDI0kP^To8kppd0(CnFmNI4lQo6h};s|sn@K|1h%+mejnC= z-me~f%(_M-3nN4+7FVDk*-^_81wA4*NV5&}QZtlH^K{`xh`l+IU1e}Fyt|pI^y^v& z&J9V>>(%Lx8fd8FXgK!XcVOnmB3TnZfznFs8cUD}cIY*Ge5LuVFE;Pr-bLf*6gQ=v z;bqG&N;LP5Ou6SO8-qe3xS{%ps#kHlEqn^()s&JmcaG$7VnX|gLQv)%Y>96t_=-|_ z_pm*X2p)(d9#6Qvtui9;cf-B<^PXI9E=kOKcj>Rx3>A8Ajwy05o>Zk5*&`8xP-`}y4tpJz8okO&0`?eUSS*j2mY zm??eByzb)RBt2xQG5aJgDj&&4XpQbw*ub$Rjx%lFqUI~tt###FLJys&U-p+`TeoE( zKq7>p@A?EqC=YhN^VGvR=Mu%*@*I2}Bs0{0EndM=8j93rC%B`(s}-_}wtMg_|57>< zp$6ru_NC~w?TJyduP5kBuC*LpqTb&|3oX_JSVc$YRf}0#R-{-`2OLe{9cVgsD&CRU zp}IR5&g=NOSX2-iqh%22&KA3mL`XvsxISBrdX@6WKi6n2cC38s-CbDUO>jD}vTSaV z%zNmo@0iQdlyzI^q%U9m_;QG_R%kb#%;-uyn@~f^^IrJ1h(ZVXEyn~ z=o4yKsXkjV<0jK2W&gTPW#r7tolueM2S~&@D4lzZV^#B;h^v-O$^9y$b^{UWkMtR% zd|f$t_yNi8gKxxe7)eoS1WjResicaCvV$9JA=jGZkqBids&`?N`19TIAos0~-cT#& z4%5=rv0yrH4W&&w?8Z_Ssx5?XH$K&Kr}z_l)w&KPCI*%I25HXY&RUj{wm0bs8c2i_ zWFM$)d7VD}{7x)IwzGOV*6#r#T*Hng{vR%#MU*ZnwP7U+zd0j&g#7cK*i`9a7YT+_ zIZTx`C%?E;E%Tc3Lsa7EMujtj+IZ`jxk>b1J6>6JzkTa~=nKDyWmgsp{F=c{FH&A4 zLI|3hTVGhb-0vvjUTba8_Oa*wS6O^i2?e*oLh*zf(ZSDM>Xl;_o)WX?t$GGXgg-QN zvV+{|3}koBSGUzH89PK7I~je=qea(sTVZjG;aeCzXq>!-D}1OVN_VWj+S~doH8tAF z+JsII9}s{%QHN#)@whZVn{VlsxTwU4IEE3?8$t+c*# zOou(OuK%4qWw^JZhD1n0BSq+UYUt#b)E-Y&{29Kl6dJi$Mz*|{5~MTH$l3i+t>B@A z<*&hNo5r81U!O9xxGty5fJ7i6HQn#R!aPb#1Z9qQt8TvP7}UvInas&AP>@Vu&~@6*2>awQbd#c# z2wOgd!TRpm{Tps^4*Kd!1KBRK&B4VN#*hepsE26q4clApZ-bFHCmrO=T@Kti!~3%5 zqeeBwq%`=t)P?<#vAyr~>@$%FS!lOCi>|?}L^ewHb{%I^%*@wdmBw>{$3^mo!CwqF z3ccmBX>gFeG(@S>MGIx|gj``}2*!#j*-JL-NQ4U1kd%hjLH!CskPL;Dd?_vJIdfLm zcu6Hn&3$y(;OFrJ+M8~;Uv>$a5HVx+kZ;LhKTVv>kSwtl1= zm`GfYSEhSYX8?GJnG3nMREM2Nfb}p_sPXRyA-wkhH+Jl$NE#8ZuPnH(HGQ2sw(d@4 z65x*fSb}*nJg;f(@v4Zie2#J7(!2ruai?&!0TsHv?|dgsUrQb;Y}q3Za8nBuDk5p? zRqFl8EM^`yw@9~hi+~4*_%4&pc|B7OXh^yl`K-BEKhX#9^XyIQk>`(C9N(j~4EC>1 zjx7wG9%o>TVJlhB%D7s;MchQ<2efC|laFA0*<%gGy2C}Wn6aUgnVOB9qdoOjz*7~h zlB%3^^AxBuioNikKdw(TK?8ntDeQf>yks>WQgQ5grebcNYWgtX^R~KP3*2JUYJSjc z&+@st=P%aj0Y4DEwk>;Z?@}Qb<8wRI$AB~Sg_(fc2W6$%4rfdLwiKYTt{?dE&HBSU z;6EF@_sbR^c&R@1N_Izat<~&PI<3njqESaY-FkQ(8E-01T;85_#D)}B1?;)R$AFy z1$EeFOFF0%aT?H|E{W{5wuS#TFA&~=NFftK2uj&16B3#D(EJjBMk)w;Pu_d>H=jYt zH2~VEA?QHxBY$k?x_?bPgn*`~;_kO%5kNWy_R*n5PX`Vm0*JUFzega?wdn-@bN{Z} zfq)jW3(&497?-pO`k3u5Mbb;ncP(UChX{^){uWhH{HLgj7@Gk~Q2kAqe0`B#@=3}s zmdu!X!oB#tsH!0sQh1kMjU=$2x=Rjwnhr|XH>y*>)6z0fx$YRanA*UEDnkJF3rvEr z*SZ}E`$ffYc+4AR%G(e@mJ~Pq*)KGee2;*8uBp(#M?wqRZMao_77hDCt~`hXYVJ#T z;L?@q$GiF1vg?dYvV3E!Nq^0;0jFuW-Xna=Wj%6Zc&w)fgiQu@TFGa#u{C<6&-N$U zT_C`wfRfpbTc|=ka-2$E-*DsoEC z;o{$022A|680*sl$!I4hM$s9a%?iL`vU(EVR{v<;X4US^&ZzAKtgBSPD4>_1iIFx^ z?@@nG8esa88N`z*25GXqRaDm7b5Ve8?aTHWMV0xl@sl{cv!3q)td%!V;fG81p8oFM zyED!C+JKq0vl%C@3>M~JQl-Kfq{}2L#7#_9WFz`yd4#IUpyAD|EO~Q-w2&RY@%FtKz#eyN>n-LEwyZrH zw>nr|`~+C_GKC;})`ZIDOD;1_tjDc@8Eu$cCHxEXH>51kax| zEzQjKIp_iwpLxq+i5{}xOt5nno498I*a!Y=o$dIXI-hiZYuj{^mjgzB)97altB-M@ z&ALEO5_tz;PnCV@f*40|t*mMoR78_<0rMFy%A{ekf10i)S*3lXzXDj5d=7W8B;wUd zIGAP3~S@a?Qr; zjPnaZUr^61!MGaY={Z%7qJTcy5OY$IaY?`;l^)$(?*fy`gs#Ufg+6mb3843d^h=6~Eg#*M5PEVheZk)> z1yJ6_Q6qWtw_?To@3CffWqHR40A)`8=p0#Lp-sK}B6cgKABUX>P-Cv_9`aNxnQWFD zRk<;Z4(+{wF7wIJrwg6Ubj{WwaqY-+cFqP=G`stO<0~f`_9xPzF0J~v_d@{H*||HW zx`DD7r#w2@BlgT48UR!#kssH*U9e3ij+bA2Z9B>42cXt5j>Jjddcqh;qo+8lKd+LH z0;(J9t3fEVD1D(4k2%kBi!po~PzI5Kagz61MmAC#wK%y|!XqqzX09Enid$rbq&)Eo zuW#mw&wL4}&<)|c3463G{rKVglB?}4`Dj1`(`1*v1l>d@SLvzMcz%laOak>Jd|{Wz$7HF+h)`rK^TR`PCnlvGuLult$T*1Nt!L{G1ey-lO#Z+}o;o7FSG3 z0VUvc=j!4PrsC)(y?Kd%_VUx$fNuXB!Y8gxxEiq7}oB zqX?h_BCOWHM#k zHdO&#X;z)Izj1!h`GK((cJ3X>0m!NkS;WD;9A$|wG~G-Co!f|0Uo-VM*>-PO&LqZ{AG+Y`txUn;LS z)Dnmw5K@b#oHtCcx5oF!)(7{-_hkoP$kR_?l~D)3qU_3>Q)U{Bb%hNfU5-Djd2z|= zCtxu*2WXQmPR?vBPU(!(#!mw_K-4C4|ICduZmh+qj|yYefH9jO$v0-teuz9Q7K;6P z)fF&1FU2*v<=A^2Z*S`swMOl`os0%feSn!&&$RSvF_C6358>U4vM0YzleX zYrH*Azvu20eMRlxxF}pH-ZQ(Jg@*)ZQJlToHzi(JL7?`y~Hv{Os(bT4eVDzg*JhyiG z+tQ8?UjbUUMLic+*_B$B=7*En<1|dyaub^fsxVV!Qzw2Q>YoByL^y(S50@5vJ=8#p zL84#p;uq!PWggISRSJ>7nSYDl=>}Rg79ii34~V-LCmQB;GF;vUQJyE;T2>7!mBsGL3pKX1HvoGf_4>e zH4zRFUYQx+r~u&=PVk?@tB!mSUMcj0@akH%Q@j9WpHhLbJ>OKRzK?&$voj`dyFOc& zXEf-RztuGL0O1uaHVCi65)ifL>GPFDhcro*Er1MEa~cQx&Jw~0nX?{To<<*3Q-BO# znWj7F_^<8LrxkdmL|+9mXz=p-qO|^%46Nx=ezV!uy5XrxpL38}?|}>wbU+666(9q( zF_7V16ObV|#NfKCK@1O&ft&=$pzsRFKq(AlF!BX5gym@_DHf!=0vT>)D`o&0E~ori z2A((|!^kHf14(KmTS=fcu6vH@=ntY|!aVB=E7Aa^LmO&8o<@g}wXbYI26QrzK}IzC z_+wLtlaV!U%fASuTPH+t}q3o07e0f z0vH7_3Sbn#D1cD_qX0$$i~<-1FbZH4_`3rCD*wkG?j6n&W~N9@hx31--(?{GAA${j zoO+sL>%%oUY-X_0!{!JZF>LOzft(%W^dRpKg^dn2G;Cl!ARac5`&YsC=k)-vmH-OK z;oI1VPxl4dV4tA;bB%;20b{{$6!qQhJjMR8CH{{s35Wz91!e)O3t*WDjJ)pd0C(|6Kv_93N!IAP)xlH!f@-p9atP z!83i3>w~Nr{Er{V*+KqJ1{=uxL5@!e8+hgq`f1=A{N5Pk`d~eP0X9b1m|z3_N3ek! zQ~viTUhE4=0xjp% zfd#ICKe#D8yAR|B*`FSV+aLHZ*YN-G{bPP`9DntV-QZ${3odj8@`pU&m)+@S*MwDY zK0PKt{GjXbw&&l5{+FH)o*&#p;Qslm^PjF`ftv>|xbQDRQINywF*u!`f&ba@oc}jI NKUkAHy?Np4KLGbzf%^ae literal 0 HcmV?d00001 diff --git a/unittest/com/jacob/test/powerpoint/PowerpointTest.java b/unittest/com/jacob/test/powerpoint/PowerpointTest.java index 0bb5b31..2bb42b7 100644 --- a/unittest/com/jacob/test/powerpoint/PowerpointTest.java +++ b/unittest/com/jacob/test/powerpoint/PowerpointTest.java @@ -1,13 +1,13 @@ package com.jacob.test.powerpoint; - /** - * $Id$ - * - * This is really more of a multi threaded tester - *

      - * 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. - */ +/** + * $Id$ + * + * This is really more of a multi threaded tester + *

      + * 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. + */ import com.jacob.activeX.ActiveXComponent; import com.jacob.com.ComFailException; 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. - * The submitter stated they had the problem on windows 2000 with office 2000 - * I have been unable to duplicate on windows XP with office 2003. - * I am comitting this to the tree just in case we need to come back to it. + * The submitter stated they had the problem on windows 2000 with office 2000 I + * have been unable to duplicate on windows XP with office 2003. I am comitting + * this to the tree just in case we need to come back to it. *

      * This relies on BaseTestCase to provide the root path to the file under test *

      - * 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. + * 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 PowerpointTest extends BaseTestCase { +public class PowerpointTest extends BaseTestCase { 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 - * 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. - * + * 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 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++) { - System.out.println("toInt=" + ai[i]); + /** + * + */ + public void testShortSafeArray() { + 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++) { - System.out.println("toDouble=" + ad[i]); + + assertEquals("single get failed: ", sourceData[2], saUnderTest + .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 }); - System.out.println("sa int=" + sa); - ai = sa.toIntArray(); - for (int i = 0; i < ai.length; i++) { - System.out.println("toInt=" + ai[i]); + // test conversion + double[] extractedFromSafeArrayDouble = saUnderTest.toDoubleArray(); + for (int i = 0; i < extractedFromSafeArrayDouble.length; i++) { + assertEquals("" + i, new Double(sourceData[i]).doubleValue(), + extractedFromSafeArrayDouble[i]); } - ad = sa.toDoubleArray(); - for (int i = 0; i < ad.length; i++) { - System.out.println("toDouble=" + ad[i]); + // test conversion + Variant extractedFromSafeArrayVariant[] = saUnderTest.toVariantArray(); + 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 }); - System.out.println("sa double=" + sa); - sa.fromFloatArray(new float[] { 1.5F, 2.5F, 3.5F }); - System.out.println("sa float=" + sa); - sa.fromBooleanArray(new boolean[] { true, false, true, false }); - System.out.println("sa bool=" + sa); - av = sa.toVariantArray(); - for (int i = 0; i < av.length; i++) { - System.out.println("toVariant=" + av[i]); - } - sa.fromCharArray(new char[] { 'a', 'b', 'c', 'd' }); - System.out.println("sa char=" + sa); - sa.fromStringArray(new String[] { "hello", "from", "java", "com" }); - System.out.println("sa string=" + sa); - av = sa.toVariantArray(); - for (int i = 0; i < av.length; i++) { - System.out.println("toVariant=" + av[i]); - } - sa.fromVariantArray(new Variant[] { - new Variant(1), new Variant(2.3), new Variant("hi") }); - System.out.println("sa variant=" + sa); + assertEquals("single get failed: ", sourceData[2], saUnderTest + .getInt(2)); } + /** + * + */ + 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() { int[] lowerBounds = new int[] { 0, 0, 0 }; int[] dimensionSizes = new int[] { 3, 3, 3 }; @@ -75,13 +203,29 @@ public class SafeArrayBasicTest extends BaseTestCase { dimensionSizes); System.out.println("Num Dimensions = " + sa3x3.getNumDim()); - for (int i = 1; i <= sa3x3.getNumDim(); i++) { - System.out.println("Dimension number = " + i); - System.out.println("Lower bound = " + sa3x3.getLBound(i)); - System.out.println("Upper bound = " + sa3x3.getUBound(i)); + for (int safeArrayDimension = 1; safeArrayDimension <= sa3x3 + .getNumDim(); safeArrayDimension++) { + int configArrayIndex = safeArrayDimension - 1; + 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 }; for (int i = 0; i < 3; i++) { @@ -90,10 +234,17 @@ public class SafeArrayBasicTest extends BaseTestCase { indices[1] = j; for (int k = 0; k < 3; k++) { indices[2] = k; + + int fill = 0; fill = i * 100 + j * 10 + k; sa3x3.setInt(indices, fill); - System.out.println("sa[" + i + "][" + j + "][" + k + "] = " - + sa3x3.getInt(indices)); + assertEquals(fill, 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)); } } } diff --git a/unittest/com/jacob/test/safearray/SafeArrayContents.java b/unittest/com/jacob/test/safearray/SafeArrayContents.java index b97a7c8..1e9cc0a 100644 --- a/unittest/com/jacob/test/safearray/SafeArrayContents.java +++ b/unittest/com/jacob/test/safearray/SafeArrayContents.java @@ -267,7 +267,7 @@ public class SafeArrayContents extends BaseTestCase { fail("Failed to catch expected exception"); } catch (ComFailException cfe) { // do nothing - //cfe.printStackTrace(); + // cfe.printStackTrace(); } } } diff --git a/unittest/com/jacob/test/safearray/SafeArrayDispatchTest.java b/unittest/com/jacob/test/safearray/SafeArrayDispatchTest.java index e64e244..43796f8 100644 --- a/unittest/com/jacob/test/safearray/SafeArrayDispatchTest.java +++ b/unittest/com/jacob/test/safearray/SafeArrayDispatchTest.java @@ -7,6 +7,9 @@ import com.jacob.com.SafeArray; import com.jacob.com.Variant; import com.jacob.test.BaseTestCase; +/** + * Test class to verify dispatch with SafeArray + */ public class SafeArrayDispatchTest extends BaseTestCase { public void testDispatchWithSafeArray() { try { @@ -36,7 +39,7 @@ public class SafeArrayDispatchTest extends BaseTestCase { assertTrue(result.toString().equals("6")); } catch (ComException e) { e.printStackTrace(); - fail("script failure "+e); + fail("script failure " + e); } } } diff --git a/unittest/com/jacob/test/safearray/SafeArrayLeak.java b/unittest/com/jacob/test/safearray/SafeArrayLeak.java index deabe04..f0405bc 100644 --- a/unittest/com/jacob/test/safearray/SafeArrayLeak.java +++ b/unittest/com/jacob/test/safearray/SafeArrayLeak.java @@ -3,191 +3,175 @@ package com.jacob.test.safearray; import com.jacob.activeX.ActiveXComponent; import com.jacob.com.ComThread; import com.jacob.com.Dispatch; -import com.jacob.com.JacobObject; +import com.jacob.com.JacobReleaseInfo; import com.jacob.com.SafeArray; import com.jacob.com.Variant; import com.jacob.test.BaseTestCase; /** - * This test program demonstrates a weak in the setString(int[],String) method in SafeArray. - * To see the leak: + * This test program demonstrates a weak in the setString(int[],String) method + * in SafeArray. To see the leak: *

        *
      • Bring up the windows task manager and click on the performance tab. *
      • Run the test program *
      - * You should see the Page File Usage History graph rise at te end of every cycle. - * Running the same program with setString(r,c,String) does not show the same symptoms + * You should see the Page File Usage History graph rise at te end of every + * 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() { - ActiveXComponent xl = null; - Dispatch workbooks = null; - Dispatch workbook = null; - Dispatch workSheets = null; - Dispatch sheet = null; - Dispatch tabCells = null; - SafeArray sa = null; - - //-Dcom.jacob.autogc=true - System.out.println("Jacob version: "+JacobObject.getBuildVersion()); - - for(int t = 0; t < 10; t++) { - // look at a large range of cells + ActiveXComponent xl = null; + Dispatch workbooks = null; + Dispatch workbook = null; + Dispatch workSheets = null; + Dispatch sheet = null; + Dispatch tabCells = null; + SafeArray sa = null; + + // -Dcom.jacob.autogc=true + System.out.println("Jacob version: " + JacobReleaseInfo.getBuildVersion()); + + for (int t = 0; t < 10; t++) { + // look at a large range of cells String position = "A7:DM8934"; - - try { - xl = new ActiveXComponent("Excel.Application"); - System.out.println("Excel version=" + xl.getProperty("Version")); - + + try { + xl = new ActiveXComponent("Excel.Application"); + System.out + .println("Excel version=" + xl.getProperty("Version")); + xl.setProperty("Visible", new Variant(false)); workbooks = xl.getProperty("Workbooks").toDispatch(); - - workbook = Dispatch.get(workbooks,"Add").toDispatch(); - + + workbook = Dispatch.get(workbooks, "Add").toDispatch(); + workSheets = Dispatch.get(workbook, "Worksheets").toDispatch(); - + sheet = Dispatch.get(workbook, "ActiveSheet").toDispatch(); // grab the whole range specified above. - tabCells = Dispatch.invoke(sheet, "Range", Dispatch.Get, - new Object[] { position }, - new int[1]).toDispatch(); - + tabCells = Dispatch.invoke(sheet, "Range", Dispatch.Get, + new Object[] { position }, new int[1]).toDispatch(); + sa = Dispatch.get(tabCells, "Value").toSafeArray(true); - + System.out.println("Ub0=" + sa.getUBound(1)); // nbCol System.out.println("Ub1=" + sa.getUBound(2)); // nbLgn - + // number of rows int nbLgn = sa.getUBound(2); // number of columns int nbCol = sa.getUBound(1); - + int[] colLgn = new int[] { 0, 0 }; - + // 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; - - for(int j = 1; j <= nbCol; j++) { + + for (int j = 1; j <= nbCol; j++) { colLgn[0] = j; // 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 sa.setString(colLgn, "test"); } } - + Dispatch.put(tabCells, "Value", sa); - + Variant f = new Variant(false); Dispatch.call(workbook, "Close", f); System.out.println("Close"); - } - catch(Exception e) { - e.printStackTrace(); - } - finally { - - if (sa != null) { - try { - sa.safeRelease(); - } - catch(Exception e) { - e.printStackTrace(); - } - finally { - sa = null; - } + } catch (Exception e) { + e.printStackTrace(); + } finally { + + if (sa != null) { + try { + sa.safeRelease(); + } catch (Exception e) { + e.printStackTrace(); + } finally { + sa = null; + } } - + if (tabCells != null) { - try { - tabCells.safeRelease(); - } - catch(Exception e) { - e.printStackTrace(); - } - 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; - } + try { + tabCells.safeRelease(); + } catch (Exception e) { + e.printStackTrace(); + } 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 (workbook != null) { - try { - workbook.safeRelease(); - } - catch(Exception e) { - e.printStackTrace(); - } - finally { - workbook = null; - } - } - - if (workbooks != null) { - try { - workbooks.safeRelease(); - } - catch(Exception e) { - e.printStackTrace(); - } - finally { - workbooks = null; - } - } - - if (xl != null) { - try { - xl.invoke("Quit", new Variant[] {}); - } - catch(Exception e) { - e.printStackTrace(); - } - - try { - xl.safeRelease(); - } - catch(Exception e) { - e.printStackTrace(); - } - finally { - xl = null; - } - } - - ComThread.Release(); - } - } + try { + workbook.safeRelease(); + } catch (Exception e) { + e.printStackTrace(); + } finally { + workbook = null; + } + } + + if (workbooks != null) { + try { + workbooks.safeRelease(); + } catch (Exception e) { + e.printStackTrace(); + } finally { + workbooks = null; + } + } + + if (xl != null) { + try { + xl.invoke("Quit", new Variant[] {}); + } catch (Exception e) { + e.printStackTrace(); + } + + try { + xl.safeRelease(); + } catch (Exception e) { + e.printStackTrace(); + } finally { + xl = null; + } + } + + ComThread.Release(); + } + } } } diff --git a/unittest/com/jacob/test/safearray/SafeArrayReleaseTest.java b/unittest/com/jacob/test/safearray/SafeArrayReleaseTest.java index 1aeca13..1ea6de3 100644 --- a/unittest/com/jacob/test/safearray/SafeArrayReleaseTest.java +++ b/unittest/com/jacob/test/safearray/SafeArrayReleaseTest.java @@ -7,111 +7,83 @@ import com.jacob.test.BaseTestCase; /** *

      - * 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. - *

      - * 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| - +------------+ +---------+ - * + * 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. *

      - * 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. + * 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| +------------+ +---------+ + * + *

      + * 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 { - final static int MAX = 300; - public void testSaveArrayRelease() { - int count; - System.out.println("Starting test for max = "+MAX); - for(count = 1; count - * 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. + * 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. *

      * This relies on BaseTestCase to provide the root path to the file under test */ public class SafeArrayViaExcel extends BaseTestCase { + + /** + * verify safe arrays work with standard applications, Excel in this case + */ public void testSafeArrayViaExcel() { - // deprecated - // System.runFinalizersOnExit(true); ActiveXComponent xl = new ActiveXComponent("Excel.Application"); try { @@ -26,8 +31,9 @@ public class SafeArrayViaExcel extends BaseTestCase { Dispatch workbook = Dispatch.call( workbooks, "Open", - getWindowsFilePathToPackageResource("SafeArrayViaExcel.xls",this.getClass())) - .toDispatch(); + getWindowsFilePathToPackageResource( + "SafeArrayViaExcel.xls", this.getClass())) + .toDispatch(); System.out.println("Opened File - SafeArrayViaExcel.xls\n"); Dispatch sheet = Dispatch.get(workbook, "ActiveSheet").toDispatch(); cell = Dispatch.invoke(sheet, "Range", Dispatch.Get, @@ -61,7 +67,7 @@ public class SafeArrayViaExcel extends BaseTestCase { System.out.println("Closed File\n"); } catch (Exception e) { e.printStackTrace(); - fail("Caught Exception "+e); + fail("Caught Exception " + e); } finally { xl.invoke("Quit", new Variant[] {}); } diff --git a/unittest/com/jacob/test/vbscript/ScriptTest.java b/unittest/com/jacob/test/vbscript/ScriptTest.java index 9eb2e7b..755f8d4 100644 --- a/unittest/com/jacob/test/vbscript/ScriptTest.java +++ b/unittest/com/jacob/test/vbscript/ScriptTest.java @@ -1,8 +1,12 @@ 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.activeX.*; /** * 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 lang = "VBScript"; ActiveXComponent sC = new ActiveXComponent("ScriptControl"); - sControl = (Dispatch) sC.getObject(); + sControl = sC.getObject(); Dispatch.put(sControl, "Language", lang); ScriptTestErrEvents te = new ScriptTestErrEvents(); de = new DispatchEvents(sControl, te); diff --git a/unittest/com/jacob/test/vbscript/ScriptTest2.java b/unittest/com/jacob/test/vbscript/ScriptTest2.java index 0963b32..0fe91ea 100644 --- a/unittest/com/jacob/test/vbscript/ScriptTest2.java +++ b/unittest/com/jacob/test/vbscript/ScriptTest2.java @@ -1,8 +1,14 @@ 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.activeX.*; /** * 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 * DispatchProxy objects. *

      - * 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. + * 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 ScriptTest2 extends BaseTestCase { @@ -31,8 +38,8 @@ public class ScriptTest2 extends BaseTestCase { ComThread.InitSTA(); ScriptTestSTA script = new ScriptTestSTA(); try { - Thread.sleep(1000); - } catch (InterruptedException ie){ + Thread.sleep(1000); + } catch (InterruptedException ie) { // should we get this? } @@ -50,7 +57,7 @@ public class ScriptTest2 extends BaseTestCase { System.out.println("called quit"); } catch (ComException e) { e.printStackTrace(); - fail("caught exception"+e); + fail("caught exception" + e); } finally { Integer I = null; for (int i = 1; i < 1000000; i++) { @@ -63,11 +70,11 @@ public class ScriptTest2 extends BaseTestCase { 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() { try { diff --git a/unittest/com/jacob/test/vbscript/ScriptTest2ActiveX.java b/unittest/com/jacob/test/vbscript/ScriptTest2ActiveX.java index 17da960..58c7898 100644 --- a/unittest/com/jacob/test/vbscript/ScriptTest2ActiveX.java +++ b/unittest/com/jacob/test/vbscript/ScriptTest2ActiveX.java @@ -26,8 +26,9 @@ import com.jacob.test.BaseTestCase; * multiple threads to access a Dispatch pointer, then create that many * DispatchProxy objects. *

      - * 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. + * 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 ScriptTest2ActiveX extends BaseTestCase { public static ActiveXComponent sC; @@ -42,9 +43,9 @@ public class ScriptTest2ActiveX extends BaseTestCase { ScriptTest2ActiveXSTA script = new ScriptTest2ActiveXSTA(); try { Thread.sleep(1000); - } catch (InterruptedException ie){ - // should we get this? - } + } catch (InterruptedException ie) { + // should we get this? + } // get a thread-local Dispatch from sCon ActiveXComponent sc = new ActiveXComponent(sCon.toDispatch()); @@ -60,7 +61,7 @@ public class ScriptTest2ActiveX extends BaseTestCase { System.out.println("called quit"); } catch (ComException e) { e.printStackTrace(); - fail("blew up with Com Exception "+e); + fail("blew up with Com Exception " + e); } finally { Integer I = null; for (int i = 1; i < 1000000; i++) { diff --git a/unittest/com/jacob/test/vbscript/ScriptTest3.java b/unittest/com/jacob/test/vbscript/ScriptTest3.java index 51c29b3..2745ec6 100644 --- a/unittest/com/jacob/test/vbscript/ScriptTest3.java +++ b/unittest/com/jacob/test/vbscript/ScriptTest3.java @@ -1,8 +1,12 @@ 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.activeX.*; /** * 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 * make calls into a component running in another thread. *

      - * 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. + * 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 ScriptTest3 extends BaseTestCase { @@ -29,13 +34,15 @@ public class ScriptTest3 extends BaseTestCase { ScriptTest3Inner script = new ScriptTest3Inner(); script.start(); try { - Thread.sleep(1000); - } catch (InterruptedException ie){ + Thread.sleep(1000); + } catch (InterruptedException ie) { // should we get this? } - Variant result = Dispatch.call(sControl, "Eval", getSampleVPScriptForEval()); - System.out.println("eval(" + getSampleVPScriptForEval() + ") = " + result); + Variant result = Dispatch.call(sControl, "Eval", + getSampleVPScriptForEval()); + System.out.println("eval(" + getSampleVPScriptForEval() + ") = " + + result); System.out.println("setting quit"); ScriptTest3.quit = true; } catch (ComException e) { @@ -54,13 +61,14 @@ public class ScriptTest3 extends BaseTestCase { System.out.println("OnInit"); String lang = "VBScript"; sC = new ActiveXComponent("ScriptControl"); - sControl = (Dispatch) sC.getObject(); + sControl = sC.getObject(); Dispatch.put(sControl, "Language", lang); ScriptTestErrEvents te = new ScriptTestErrEvents(); de = new DispatchEvents(sControl, te); System.out.println("sControl=" + sControl); - while (!quit) + while (!quit) { sleep(100); + } ComThread.Release(); } catch (Exception e) { e.printStackTrace(); diff --git a/unittest/com/jacob/test/vbscript/ScriptTest3ActiveX.java b/unittest/com/jacob/test/vbscript/ScriptTest3ActiveX.java index 1a20f53..e75b268 100644 --- a/unittest/com/jacob/test/vbscript/ScriptTest3ActiveX.java +++ b/unittest/com/jacob/test/vbscript/ScriptTest3ActiveX.java @@ -1,8 +1,11 @@ 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.activeX.*; /** * 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()); - System.out - .println("eval(" + getSampleVPScriptForEval() - + ") = " + result); + System.out.println("eval(" + getSampleVPScriptForEval() + ") = " + + result); System.out.println("setting quit"); ScriptTest3ActiveX.quit = true; } catch (ComException e) { @@ -58,8 +60,9 @@ public class ScriptTest3ActiveX extends BaseTestCase { ScriptTestErrEvents te = new ScriptTestErrEvents(); de = new DispatchEvents(sC, te); System.out.println("sControl=" + sC); - while (!quit) + while (!quit) { sleep(100); + } ComThread.Release(); } catch (Exception e) { e.printStackTrace(); diff --git a/unittest/com/jacob/test/vbscript/ScriptTestActiveX.java b/unittest/com/jacob/test/vbscript/ScriptTestActiveX.java index 9d3a57a..210db85 100644 --- a/unittest/com/jacob/test/vbscript/ScriptTestActiveX.java +++ b/unittest/com/jacob/test/vbscript/ScriptTestActiveX.java @@ -1,52 +1,53 @@ 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.activeX.*; /** - * In this case the component is created and used in the same thread - * and it's an Apartment Threaded component, so we call InitSTA. + * In this case the component is created and used in the same thread and it's an + * Apartment Threaded component, so we call InitSTA. *

      * 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 ScriptTestActiveX extends BaseTestCase { - public void testActiveXScript() { + public void testActiveXScript() { ComThread.InitSTA(true); - DispatchEvents de = null; + DispatchEvents de = null; - try { - String lang = "VBScript"; - ActiveXComponent sC = new ActiveXComponent("ScriptControl"); - sC.setProperty("Language",lang); - ScriptTestErrEvents te = new ScriptTestErrEvents(); - de = new DispatchEvents(sC, te); - if (de == null){ - System.out.println("null returned when trying to create DispatchEvents"); - } - Variant result; - result = sC.invoke("Eval",getSampleVPScriptForEval()); - // call it twice to see the objects reused - result = sC.invoke("Eval",getSampleVPScriptForEval()); - // call it 3 times to see the objects reused - result = sC.invoke("Eval",getSampleVPScriptForEval()); - System.out.println("eval("+getSampleVPScriptForEval()+") = "+ result); - } catch (ComException e) { - e.printStackTrace(); - } - finally - { - Integer I = null; - for(int i=1;i<1000000;i++) - { - I = new Integer(i); - } - System.out.println(I); + try { + String lang = "VBScript"; + ActiveXComponent sC = new ActiveXComponent("ScriptControl"); + sC.setProperty("Language", lang); + ScriptTestErrEvents te = new ScriptTestErrEvents(); + de = new DispatchEvents(sC, te); + if (de == null) { + System.out + .println("null returned when trying to create DispatchEvents"); + } + Variant result; + result = sC.invoke("Eval", getSampleVPScriptForEval()); + // call it twice to see the objects reused + result = sC.invoke("Eval", getSampleVPScriptForEval()); + // call it 3 times to see the objects reused + result = sC.invoke("Eval", getSampleVPScriptForEval()); + System.out.println("eval(" + getSampleVPScriptForEval() + ") = " + + result); + } catch (ComException e) { + e.printStackTrace(); + } finally { + Integer I = null; + for (int i = 1; i < 1000000; i++) { + I = new Integer(i); + } + System.out.println(I); ComThread.Release(); ComThread.quitMainSTA(); - } - } + } + } } - diff --git a/unittest/com/jacob/test/vbscript/ScriptTestErrEvents.java b/unittest/com/jacob/test/vbscript/ScriptTestErrEvents.java index 9be2f38..c0700bf 100644 --- a/unittest/com/jacob/test/vbscript/ScriptTestErrEvents.java +++ b/unittest/com/jacob/test/vbscript/ScriptTestErrEvents.java @@ -4,17 +4,16 @@ import com.jacob.com.Variant; import com.jacob.test.BaseTestCase; /** - * Extracted from ScriptTest so everyone can see this - * Made a test solely because it made the ant test easier + * Extracted from ScriptTest so everyone can see this Made a test solely because + * it made the ant test easier */ public class ScriptTestErrEvents extends BaseTestCase { - public void Error(Variant[] args) - { - System.out.println("java callback for error!"); - } - public void Timeout(Variant[] args) - { - System.out.println("java callback for error!"); - } + public void Error(Variant[] args) { + System.out.println("java callback for error!"); + } + + public void Timeout(Variant[] args) { + System.out.println("java callback for error!"); + } } diff --git a/unittest/com/jacob/test/windowsmedia/WMPlayer.java b/unittest/com/jacob/test/windowsmedia/WMPlayer.java index 4f7e152..734d391 100644 --- a/unittest/com/jacob/test/windowsmedia/WMPlayer.java +++ b/unittest/com/jacob/test/windowsmedia/WMPlayer.java @@ -8,7 +8,7 @@ package com.jacob.test.windowsmedia; * 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. */ -import com.jacob.activeX.*; +import com.jacob.activeX.ActiveXComponent; import com.jacob.test.BaseTestCase; public class WMPlayer extends BaseTestCase {