diff --git a/java/.classpath b/java/.classpath
index 70d3166..e4b5e09 100644
--- a/java/.classpath
+++ b/java/.classpath
@@ -7,5 +7,6 @@
haveSTA
+ */
+ public static boolean haveSTA = false;
+
+ /**
+ * 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 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 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 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);
+ }
+ }
+
+ /**
+ * 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
+ */
+ @Deprecated
+ public static synchronized void RemoveObject(JacobObject o) {
+ ROT.removeObject(o);
+ }
+
+ /**
+ * @param threadModel
+ */
+ public static native void doCoInitialize(int threadModel);
+
+ /**
+ *
+ */
+ 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/java/src/com/jacob/com/Currency.java b/java/src/com/jacob/com/Currency.java
new file mode 100644
index 0000000..d7aeef4
--- /dev/null
+++ b/java/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/java/src/com/jacob/com/DateUtilities.java b/java/src/com/jacob/com/DateUtilities.java
new file mode 100644
index 0000000..5f8bf5e
--- /dev/null
+++ b/java/src/com/jacob/com/DateUtilities.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 1999-2004 Sourceforge JACOB Project.
+ * All rights reserved. Originator: Dan Adler (http://danadler.com).
+ * Get more information about JACOB at http://sourceforge.net/projects/jacob-project
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+package com.jacob.com;
+
+import java.util.Calendar;
+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));
+ }
+
+ /**
+ * 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:
+ * You're going to live here a lot
+ */
+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.
+ *
+ *
+ * @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()
+ */
+ @Override
+ protected void finalize() {
+ safeRelease();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.jacob.com.JacobObject#safeRelease()
+ */
+ @Override
+ 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 attributes
+ * @return Variant returned by underlying callN
+ */
+ public static Variant call(Dispatch dispatchTarget, String name,
+ Object... attributes) {
+ throwIfUnattachedDispatch(dispatchTarget);
+ return callN(dispatchTarget, name, attributes);
+ }
+
+ /**
+ * @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 attributes
+ * var arg list of attributes that will be passed to the
+ * underlying function
+ * @return Variant returned by underlying callN
+ */
+ public static Variant call(Dispatch dispatchTarget, int dispid,
+ Object... attributes) {
+ throwIfUnattachedDispatch(dispatchTarget);
+ return callN(dispatchTarget, dispid, attributes);
+ }
+
+ /*
+ * ============================================================ 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 attributes
+ * var args list of attributes to be passed to underlying
+ * functions
+ */
+ public static void callSub(Dispatch dispatchTarget, String name,
+ Object... attributes) {
+ throwIfUnattachedDispatch(dispatchTarget);
+ callSubN(dispatchTarget, name, attributes);
+ }
+
+ /**
+ * 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 attributes
+ * var args list of attributes to be passed to underlying
+ * function
+ */
+ public static void callSub(Dispatch dispatchTarget, int dispid,
+ Object... attributes) {
+ throwIfUnattachedDispatch(dispatchTarget);
+ callSubN(dispatchTarget, dispid, attributes);
+ }
+
+ /*
+ * ============================================================ 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");
+ }
+
+ /**
+ * Cover for native method
+ *
+ * @param disp
+ * @param dispid
+ * @param lcid
+ * @return 0 if the dispatch is still active and 1 if it has exited
+ */
+ public static native int hasExited(Dispatch disp, int dispid, int lcid);
+
+ /**
+ * The method is used to poll until it returns 1, indicating that the COM
+ * server in gone.
+ *
+ * Sourceforge feature request 2927058
+ *
+ * @param dispatchTarget
+ * @return 0 if the dispatch is still active and 1 if it has exited
+ */
+ public static int hasExited(Dispatch dispatchTarget) {
+ throwIfUnattachedDispatch(dispatchTarget);
+ return hasExited(dispatchTarget, 0, LOCALE_SYSTEM_DEFAULT);
+ }
+
+}
diff --git a/java/src/com/jacob/com/DispatchEvents.java b/java/src/com/jacob/com/DispatchEvents.java
new file mode 100644
index 0000000..62de581
--- /dev/null
+++ b/java/src/com/jacob/com/DispatchEvents.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 1999-2004 Sourceforge JACOB Project.
+ * All rights reserved. Originator: Dan Adler (http://danadler.com).
+ * Get more information about JACOB at http://sourceforge.net/projects/jacob-project
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+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.
+ *
+ * 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.
+ *
+ */
+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);
+ }
+
+ /**
+ * 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.
+ *
+ *
+ *
+ * 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 {
+
+ /**
+ * 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
+ */
+ 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
+ * @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) {
+ // JNI code apparently bypasses this check and could operate against
+ // 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())) {
+ throw new IllegalArgumentException(
+ "InvocationProxy only public classes can receive event notifications");
+ }
+ }
+ mTargetObject = pTargetObject;
+ }
+
+}
diff --git a/java/src/com/jacob/com/InvocationProxyAllVariants.java b/java/src/com/jacob/com/InvocationProxyAllVariants.java
new file mode 100644
index 0000000..a22ff96
--- /dev/null
+++ b/java/src/com/jacob/com/InvocationProxyAllVariants.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 1999-2004 Sourceforge JACOB Project.
+ * All rights reserved. Originator: Dan Adler (http://danadler.com).
+ * Get more information about JACOB at http://sourceforge.net/projects/jacob-project
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+package com.jacob.com;
+
+import java.lang.reflect.InvocationTargetException;
+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
+ *
+ *
+ * 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
+ * it to the finalizer it will call the release from another thread, which may
+ * result in a segmentation violation.
+ */
+public class JacobObject {
+
+ /**
+ * Standard constructor that adds this JacobObject to the memory management
+ * pool.
+ */
+ public JacobObject() {
+ ROT.addObject(this);
+ }
+
+ /**
+ * 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 useful 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 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(Thread.currentThread().getName() + ": "
+ + istrMessage);
+ }
+ }
+
+ /**
+ * force the jacob DLL to be loaded whenever this class is referenced
+ */
+ static {
+ LibraryLoader.loadJacobLibrary();
+ }
+
+}
\ No newline at end of file
diff --git a/java/src/com/jacob/com/JacobReleaseInfo.java b/java/src/com/jacob/com/JacobReleaseInfo.java
new file mode 100644
index 0000000..c8d8186
--- /dev/null
+++ b/java/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/java/src/com/jacob/com/LibraryLoader.java b/java/src/com/jacob/com/LibraryLoader.java
new file mode 100644
index 0000000..85f9a16
--- /dev/null
+++ b/java/src/com/jacob/com/LibraryLoader.java
@@ -0,0 +1,230 @@
+/*
+ * 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
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+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.
+ *
+ *
+ * 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.
+ *
+ *
+ * JACOB_DLL_PATH submitted sourceforge ticket 1493647 Added 1.11
+ * The DLL name is "jacob\
+ * 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.
+ *
+ * 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
+ */
+ protected static final boolean USE_AUTOMATIC_GARBAGE_COLLECTION = "true"
+ .equalsIgnoreCase(System.getProperty("com.jacob.autogc"));
+
+ /**
+ * If the code is ran from an applet that is called from javascript the Java
+ * Plugin does not give full permissions to the code and thus System
+ * properties cannot be accessed. They can be accessed at class
+ * initialization time.
+ *
+ * The default behavior is to include all classes in the ROT, setting a
+ * boolean here to indicate this prevents a call to System.getProperty as
+ * part of the general call flow.
+ */
+ protected static final Boolean INCLUDE_ALL_CLASSES_IN_ROT = Boolean
+ .valueOf(System.getProperty("com.jacob.includeAllClassesInROT",
+ "true"));
+
+ /**
+ * 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.
+ */
+ 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
+ */
+ private static HashMap
+ * This method does not need to be threaded because the only concurrent
+ * modification risk is on the hash map that contains all of the thread
+ * related hash maps. The individual thread related maps are only used on a
+ * per thread basis so there isn't a locking issue.
+ *
+ * In addition, this method cannot be threaded because it calls
+ * ComThread.InitMTA. The ComThread object has some methods that call ROT so
+ * we could end up deadlocked. This method should be safe without the
+ * synchronization because the ROT works on per thread basis and the methods
+ * that add threads and remove thread related entries are all synchronized
+ *
+ *
+ * @param o
+ */
+ protected static void addObject(JacobObject o) {
+ String shouldIncludeClassInROT = "true";
+ // only call System.getProperty if we are not including all classes in
+ // the ROT. This lets us run with standard Jacob behavior in Applets
+ // without the security exception raised by System.getProperty in the
+ // flow
+ if (!ROT.INCLUDE_ALL_CLASSES_IN_ROT) {
+ 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 {
+ // first see if we have a table for this thread
+ Map
+ * 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
+ * of each dimension *
+ *
+ * @param vt
+ * @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);
+ }
+
+ /**
+ * 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/java/src/com/jacob/com/Variant.java b/java/src/com/jacob/com/Variant.java
new file mode 100644
index 0000000..9aafac3
--- /dev/null
+++ b/java/src/com/jacob/com/Variant.java
@@ -0,0 +1,2235 @@
+/*
+ * Copyright (c) 1999-2004 Sourceforge JACOB Project.
+ * All rights reserved. Originator: Dan Adler (http://danadler.com).
+ * Get more information about JACOB at http://sourceforge.net/projects/jacob-project
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+package com.jacob.com;
+
+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
+ * between Java and COM. It provides a single class that can handle all data
+ * types.
+ *
+ * Just loading this class creates 3 variants that get added to the ROT
+ *
+ * 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.
+ */
+public class Variant extends JacobObject {
+
+ /**
+ * 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);
+
+ /**
+ * 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 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 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 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 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 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 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 object VT_UNKNOWN */
+ public static final short VariantObject = 13;
+
+ /** variant's type is object VT_DECIMAL */
+ public static final short VariantDecimal = 14;
+
+ // VT_I1 = 16
+
+ /** variant's type is byte VT_UI1 */
+ public static final short VariantByte = 17;
+
+ // VT_UI2 = 18
+ // VT_UI4 = 19
+
+ /**
+ * 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;
+
+ // VT_UI8 = 21
+ // VT_INT = 22
+ // VT_UNIT = 23
+ // VT_VOID = 24
+ // VT_HRESULT = 25
+
+ /**
+ * This value is for reference only and is not to be used by any callers
+ */
+ public static final short VariantPointer = 26;
+
+ // VT_SAFEARRAY = 27
+ // VT_CARRARY = 28
+ // VT_USERDEFINED = 29
+
+ /** what is this? VT_TYPEMASK && VT_BSTR_BLOB 0xfff */
+ public static final short VariantTypeMask = 4095;
+
+ /** variant's type is array VT_ARRAY 0x2000 */
+ public static final short VariantArray = 8192;
+
+ /** variant's type is a reference (to IDispatch?) VT_BYREF 0x4000 */
+ public static final short VariantByref = 16384;
+
+ /*
+ * 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;
+
+ /**
+ * 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(boolean in) {
+ this(new Boolean(in));
+ }
+
+ /**
+ * Constructor that accepts a primitive rather than an object
+ *
+ * @param in
+ */
+ 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?
+ */
+ @Override
+ public native Object clone();
+
+ /**
+ * @deprecated No longer used
+ * @return null !
+ */
+ @Deprecated
+ public native Variant cloneIndirect();
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#finalize()
+ */
+ @Override
+ 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 {
+ throw new IllegalStateException(
+ "getBoolean() only legal on Variants of type VariantBoolean, not "
+ + this.getvt());
+ }
+ }
+
+ /**
+ * 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() & VariantTypeMask) == VariantBoolean
+ && (this.getvt() & VariantByref) == VariantByref) {
+ return getVariantBooleanRef();
+ } else {
+ throw new IllegalStateException(
+ "getBooleanRef() only legal on byRef Variants of type VariantBoolean, not "
+ + this.getvt());
+ }
+ }
+
+ /**
+ *
+ * @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() & VariantTypeMask) == 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() & VariantTypeMask) == 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() & VariantTypeMask) == 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() & VariantTypeMask) == 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) {
+ 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() & VariantTypeMask) == 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() & VariantTypeMask) == 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() & VariantTypeMask) == 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() & VariantTypeMask) == 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() & VariantTypeMask) == 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() & VariantTypeMask) == 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() & VariantTypeMask) == 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() & VariantTypeMask) == 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() & VariantTypeMask) == VariantVariant
+ && (this.getvt() & VariantByref) == VariantByref) {
+ if (JacobObject.isDebugEnabled()) {
+ JacobObject.debug("About to call getVariantVariant()");
+ }
+ Variant enclosedVariant = new Variant();
+ int enclosedVariantMemory = getVariantVariant();
+ enclosedVariant.m_pVariant = enclosedVariantMemory;
+ 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
+ // (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.m_pVariant = 0;
+ return enclosedVariantAsJava;
+ } else {
+ throw new IllegalStateException(
+ "getVariant() only legal on Variants of type VariantVariant, not "
+ + this.getvt());
+ }
+ }
+
+ /**
+ * @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();
+
+ /**
+ * 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");
+ }
+ }
+
+ /**
+ * 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();
+ 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(
+ "Cannot put null in as windows date");
+ // do nothing
+ } else {
+ 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
+ *
+ *
+ * @see com.jacob.com.JacobObject#safeRelease()
+ */
+ @Override
+ 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.
+ // 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");
+ }
+ }
+ }
+
+ /**
+ * 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);
+
+ /**
+ * this is supposed to create a byte array that represents the underlying
+ * variant object structure
+ */
+ protected native byte[] SerializationWriteToBytes();
+
+ /**
+ * @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();
+ }
+
+ /**
+ * 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.
+ *
+ * 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 JacobException
+ * if the calculated result was a JacobObject usually as a
+ * result of error
+ */
+ public Object toJavaObject() throws JacobException {
+ 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
+ *
+ * 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 VariantBstrBlob/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/java/src/com/jacob/com/VariantViaEvent.java b/java/src/com/jacob/com/VariantViaEvent.java
new file mode 100644
index 0000000..696a501
--- /dev/null
+++ b/java/src/com/jacob/com/VariantViaEvent.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 1999-2004 Sourceforge JACOB Project.
+ * All rights reserved. Originator: Dan Adler (http://danadler.com).
+ * Get more information about JACOB at http://sourceforge.net/projects/jacob-project
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+package com.jacob.com;
+
+/**
+ * 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 {
+
+ /**
+ * Standard constructor used by JNI event handling layer
+ */
+ public VariantViaEvent() {
+ super();
+ }
+}
diff --git a/java/src/com/jacob/com/WrongThreadException.java b/java/src/com/jacob/com/WrongThreadException.java
new file mode 100644
index 0000000..028021b
--- /dev/null
+++ b/java/src/com/jacob/com/WrongThreadException.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 1999-2004 Sourceforge JACOB Project.
+ * All rights reserved. Originator: Dan Adler (http://danadler.com).
+ * Get more information about JACOB at http://sourceforge.net/projects/jacob-project
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+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 constructor with a string message
+ *
+ * @param s
+ */
+ public WrongThreadException(String s) {
+ super(s);
+ }
+}
\ No newline at end of file
diff --git a/java/src/pm/Main.java b/java/src/pm/Main.java
index 5fe0c24..16d5490 100644
--- a/java/src/pm/Main.java
+++ b/java/src/pm/Main.java
@@ -5,9 +5,11 @@ import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import pm.application.Application;
+import pm.application.iTunes.iTunesApplicatie;
import pm.application.voorbeeld.VoorbeeldApplication;
import pm.device.Device;
import pm.device.javainput.extreme3d.Extreme3DDevice;
+import pm.device.javainput.rumblepad.RumblepadDevice;
import pm.device.jintellitype.JIntellitypeDevice;
import pm.device.wiimote.WiimoteDevice;
import pm.exception.ActionException;
@@ -50,12 +52,13 @@ public class Main {
public void start() throws Exception {
//add(new ExampleDevice());
- //add(new RumblepadDevice());
- add(new Extreme3DDevice());
+ add(new RumblepadDevice());
+ //add(new Extreme3DDevice());
add(new JIntellitypeDevice());
- add(new WiimoteDevice());
+ //add(new WiimoteDevice());
Application application = new VoorbeeldApplication();
+ application = new iTunesApplicatie();
add(application);
for (Device device : deviceList) {
diff --git a/java/src/pm/application/iTunes/iTunes.java b/java/src/pm/application/iTunes/iTunesApplicatie.java
similarity index 86%
rename from java/src/pm/application/iTunes/iTunes.java
rename to java/src/pm/application/iTunes/iTunesApplicatie.java
index 7ac1c32..89e3767 100644
--- a/java/src/pm/application/iTunes/iTunes.java
+++ b/java/src/pm/application/iTunes/iTunesApplicatie.java
@@ -6,11 +6,11 @@ import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComThread;
import com.jacob.com.Dispatch;
-public class iTunes extends Application{
+public class iTunesApplicatie extends Application{
Dispatch iTunesController;
- public iTunes() {
+ public iTunesApplicatie() {
connect();
}
@@ -44,7 +44,7 @@ public class iTunes extends Application{
}
public static void main(String argv[]) throws Exception {
- new iTunes();
+ new iTunesApplicatie();
}
}
\ No newline at end of file
diff --git a/java/src/pm/device/javainput/JavaInputDevice.java b/java/src/pm/device/javainput/JavaInputDevice.java
index 9d65079..db0a22f 100644
--- a/java/src/pm/device/javainput/JavaInputDevice.java
+++ b/java/src/pm/device/javainput/JavaInputDevice.java
@@ -8,12 +8,9 @@ import de.hardcode.jxinput.event.JXInputDirectionalEvent;
import pm.Button;
import pm.device.Device;
-import pm.device.javainput.extreme3d.Extreme3DButton;
-import pm.device.javainput.extreme3d.Extreme3DDirection;
import pm.exception.DeviceException;
import pm.exception.EventException;
import pm.exception.device.JavaInputDeviceNotFoundException;
-import pm.exception.event.UnknownDirectionException;
import pm.macro.event.Press;
import pm.macro.event.Release;
@@ -50,7 +47,7 @@ public abstract class JavaInputDevice extends Device {
}
public void processEvent(JXInputButtonEvent event) throws EventException {
- Button button = Extreme3DButton.create(event);
+ Button button = getButton(event);
if (event.getButton().getState()) {
System.out.println("Press: " + button);
add(new Press(button));
@@ -60,8 +57,8 @@ public abstract class JavaInputDevice extends Device {
}
}
- public void processEvent(JXInputDirectionalEvent event) throws UnknownDirectionException {
- Button button = Extreme3DDirection.create(event);
+ public void processEvent(JXInputDirectionalEvent event) throws EventException {
+ Button button = getButton(event);
if (event.getDirectional().isCentered()) {
if (previousDirectionalButton != null) {
System.out.println("Release: " + previousDirectionalButton);
@@ -73,4 +70,7 @@ public abstract class JavaInputDevice extends Device {
previousDirectionalButton = button;
}
}
+
+ protected abstract Button getButton(JXInputButtonEvent event) throws EventException;
+ protected abstract Button getButton(JXInputDirectionalEvent event) throws EventException;
}
diff --git a/java/src/pm/device/javainput/extreme3d/Extreme3DDevice.java b/java/src/pm/device/javainput/extreme3d/Extreme3DDevice.java
index e126b3f..914083c 100644
--- a/java/src/pm/device/javainput/extreme3d/Extreme3DDevice.java
+++ b/java/src/pm/device/javainput/extreme3d/Extreme3DDevice.java
@@ -1,11 +1,16 @@
package pm.device.javainput.extreme3d;
+import de.hardcode.jxinput.event.JXInputButtonEvent;
+import de.hardcode.jxinput.event.JXInputDirectionalEvent;
import pm.Action;
+import pm.Button;
import pm.Macro;
import pm.Target;
import pm.device.javainput.JavaInputDevice;
import pm.exception.DeviceException;
import pm.exception.MacroException;
+import pm.exception.event.UnknownButtonException;
+import pm.exception.event.UnknownDirectionException;
import pm.macro.event.Hold;
import pm.macro.event.Press;
import pm.macro.event.Release;
@@ -34,4 +39,12 @@ public class Extreme3DDevice extends JavaInputDevice {
e.printStackTrace();
}
}
+
+ protected Button getButton(JXInputButtonEvent event) throws UnknownButtonException {
+ return Extreme3DButton.create(event);
+ }
+
+ protected Button getButton(JXInputDirectionalEvent event) throws UnknownDirectionException {
+ return Extreme3DDirection.create(event);
+ }
}
diff --git a/java/src/pm/device/javainput/rumblepad/RumblepadDevice.java b/java/src/pm/device/javainput/rumblepad/RumblepadDevice.java
index 984fc3d..abef3bf 100644
--- a/java/src/pm/device/javainput/rumblepad/RumblepadDevice.java
+++ b/java/src/pm/device/javainput/rumblepad/RumblepadDevice.java
@@ -1,10 +1,16 @@
package pm.device.javainput.rumblepad;
+import de.hardcode.jxinput.event.JXInputButtonEvent;
+import de.hardcode.jxinput.event.JXInputDirectionalEvent;
import pm.Action;
+import pm.Button;
+import pm.Macro;
import pm.Target;
import pm.device.javainput.JavaInputDevice;
import pm.exception.DeviceException;
import pm.exception.MacroException;
+import pm.exception.event.UnknownButtonException;
+import pm.exception.event.UnknownDirectionException;
import pm.macro.event.Press;
public class RumblepadDevice extends JavaInputDevice {
@@ -18,7 +24,7 @@ public class RumblepadDevice extends JavaInputDevice {
public void start() {
super.start();
try {
- /*add(
+ add(
new Press(RumblepadButton.ONE),
Action.PLAY.setTarget(Target.APPLICATION));
add(
@@ -26,12 +32,23 @@ public class RumblepadDevice extends JavaInputDevice {
Action.PAUSE.setTarget(Target.APPLICATION));
add(
new Press(RumblepadButton.THREE),
- Action.RESUME.setTarget(Target.APPLICATION));*/
+ Action.RESUME.setTarget(Target.APPLICATION));
add(
- new Press(RumblepadButton.FOUR),
+ new Macro(
+ new Press(RumblepadButton.ONE)
+ ),
Action.EXIT.setTarget(Target.MAIN));
} catch (MacroException e) {
e.printStackTrace();
}
- }
+ }
+
+ protected Button getButton(JXInputButtonEvent event) throws UnknownButtonException {
+ return RumblepadButton.create(event);
+ }
+
+ protected Button getButton(JXInputDirectionalEvent event) throws UnknownDirectionException {
+ return RumblepadDirection.create(event);
+ }
+
}
diff --git a/java/src/pm/device/jintellitype/JIntellitypeDevice.java b/java/src/pm/device/jintellitype/JIntellitypeDevice.java
index 777b5e6..c2457aa 100644
--- a/java/src/pm/device/jintellitype/JIntellitypeDevice.java
+++ b/java/src/pm/device/jintellitype/JIntellitypeDevice.java
@@ -31,10 +31,7 @@ public class JIntellitypeDevice extends Device implements HotkeyListener, Intell
jit.addIntellitypeListener(this);
try {
add(
- new Macro(
- new Hotkey('r'),
- new Hotkey('i'),
- new Hotkey('k')),
+ new Hotkey(HotkeyButton.CTRL, 'x'),
Action.EXIT.setTarget(Target.MAIN));
add(
new Press(CommandButton.VOLUME_UP),
diff --git a/java/src/pm/macro/Event.java b/java/src/pm/macro/Event.java
index c27745b..2db1643 100644
--- a/java/src/pm/macro/Event.java
+++ b/java/src/pm/macro/Event.java
@@ -14,6 +14,6 @@ public abstract class Event {
}
public boolean equals(Event event) {
- return event.getClass().equals(getClass()) && event.getButton().equals(button); // Todo: controleren of equals goed werkt bij buttons van verschillende typen
+ return event.getClass().equals(getClass()) && event.getButton().equals(button);
}
}
Date javaDate = new Date(toMilliseconds (vbDate));.
+ *
+ * @param comTime
+ * COM time.
+ * @return Java time.
+ */
+ static public long convertWindowsTimeToMilliseconds(double comTime) {
+ long result = 0;
+
+ // code from jacobgen:
+ comTime = comTime - 25569D;
+ Calendar cal = Calendar.getInstance();
+ result = Math.round(86400000L * comTime)
+ - cal.get(Calendar.ZONE_OFFSET);
+ cal.setTime(new Date(result));
+ result -= cal.get(Calendar.DST_OFFSET);
+
+ return result;
+ }// convertWindowsTimeToMilliseconds()
+
+ /**
+ * converts a java date to a windows time object (is this timezone safe?)
+ *
+ * @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");
+ }
+ return convertMillisecondsToWindowsTime(javaDate.getTime());
+ }
+
+ /**
+ * Convert a Java time to a COM time.
+ *
+ * @param milliseconds
+ * Java time.
+ * @return COM time.
+ */
+ static public double convertMillisecondsToWindowsTime(long milliseconds) {
+ double result = 0.0;
+
+ // code from jacobgen:
+ Calendar cal = Calendar.getInstance();
+ cal.setTimeInMillis(milliseconds);
+ milliseconds += (cal.get(Calendar.ZONE_OFFSET) + cal
+ .get(Calendar.DST_OFFSET)); // add GMT offset
+ result = (milliseconds / 86400000D) + 25569D;
+
+ return result;
+ }// convertMillisecondsToWindowsTime()
+}
diff --git a/java/src/com/jacob/com/Dispatch.java b/java/src/com/jacob/com/Dispatch.java
new file mode 100644
index 0000000..861d6e4
--- /dev/null
+++ b/java/src/com/jacob/com/Dispatch.java
@@ -0,0 +1,872 @@
+/*
+ * Copyright (c) 1999-2004 Sourceforge JACOB Project. All rights reserved. Originator: Dan Adler
+ * (http://danadler.com). Get more information about JACOB at
+ * http://sourceforge.net/projects/jacob-project
+ *
+ * This library is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU Lesser General Public License as published by the Free Software Foundation; either version
+ * 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with this library;
+ * if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+package com.jacob.com;
+
+/**
+ * Object represents MS level dispatch object. Each instance of this points at
+ * some data structure on the MS windows side.
+ *
+ *
+ *
+ * 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);
+ } else {
+ if (JacobObject.isDebugEnabled()) {
+ JacobObject.debug("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) {
+ 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 m_pStream
+ */
+ public int m_pStream;
+
+ /**
+ * 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();
+ }
+
+ private native void MarshalIntoStream(Dispatch d);
+
+ private native Dispatch MarshalFromStream();
+
+ /**
+ * 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");
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/src/com/jacob/com/EnumVariant.java b/java/src/com/jacob/com/EnumVariant.java
new file mode 100644
index 0000000..7f16542
--- /dev/null
+++ b/java/src/com/jacob/com/EnumVariant.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 1999-2004 Sourceforge JACOB Project.
+ * All rights reserved. Originator: Dan Adler (http://danadler.com).
+ * Get more information about JACOB at http://sourceforge.net/projects/jacob-project
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+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 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[])
+ */
+ @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");
+ }
+ // 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 (targetParameters == null) {
+ throw new IllegalArgumentException(
+ "InvocationProxy: missing Variant parameters");
+ }
+ try {
+ 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) {
+ // protected classes can't be invoked against even if they
+ // 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) {
+ mVariantToBeReturned = null;
+ } 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);
+ } else {
+ mVariantToBeReturned = (Variant) mReturnedByInvocation;
+ }
+ }
+ } catch (SecurityException e) {
+ // 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);
+ }
+ } catch (IllegalArgumentException e) {
+ e.printStackTrace();
+ // 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);
+ }
+ e.printStackTrace();
+ } catch (InvocationTargetException e) {
+ // invocation of target method failed
+ e.printStackTrace();
+ }
+ return mVariantToBeReturned;
+
+ }
+}
diff --git a/java/src/com/jacob/com/JacobException.java b/java/src/com/jacob/com/JacobException.java
new file mode 100644
index 0000000..20f62d1
--- /dev/null
+++ b/java/src/com/jacob/com/JacobException.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1999-2004 Sourceforge JACOB Project.
+ * All rights reserved. Originator: Dan Adler (http://danadler.com).
+ * Get more information about JACOB at http://sourceforge.net/projects/jacob-project
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+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.
+ */
+public class JacobException extends RuntimeException {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -1637125318746002715L;
+
+ /**
+ * Default constructor. Calls super with a "No Message Provided" string
+ */
+ public JacobException() {
+ super("No Message Provided");
+ }
+
+ /**
+ * standard constructor
+ *
+ * @param message
+ */
+ public JacobException(String message) {
+ super(message);
+ }
+}
diff --git a/java/src/com/jacob/com/JacobObject.java b/java/src/com/jacob/com/JacobObject.java
new file mode 100644
index 0000000..9442360
--- /dev/null
+++ b/java/src/com/jacob/com/JacobObject.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 1999-2004 Sourceforge JACOB Project.
+ * All rights reserved. Originator: Dan Adler (http://danadler.com).
+ * Get more information about JACOB at http://sourceforge.net/projects/jacob-project
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+package com.jacob.com;
+
+/**
+ * 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.
+ *
+ *
+ *
+ * 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.
+ *
+ * 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.
+ */
+ 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";
+
+ /**
+ * 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
+ * This will remove an object from the ROT
+ * This does not need to be synchronized because only the rot
+ * modification related methods need to synchronized. Each
+ * individual map is only modified in a single thread.
+ * @param o
+ */
+ @Deprecated
+ protected static void removeObject(JacobObject o) {
+ Map
+ * 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);
+
+ /**
+ * 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.
+ *
+ *