⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 variant.java

📁 java 调用windows的api
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * Variant.java -
 *
 * This file is part of the Jawin Project: http://jawinproject.sourceforge.net/
 * 
 * Please consult the LICENSE file in the project root directory,
 * or at the project site before using this software.
 */

/* $Id: Variant.java,v 1.9 2004/07/31 21:20:05 arosii_moa Exp $ */

package org.jawin;

import java.io.IOException;
import java.util.Date;

import org.jawin.constants.VarTypes;
import org.jawin.constants.WellKnownGUIDs;
import org.jawin.io.DateUtil;
import org.jawin.io.LittleEndianInputStream;
import org.jawin.io.LittleEndianOutputStream;
import org.jawin.win32.SAFEARRAY;

/**
 * The Jawin equivalent of the Windows Variant type.
 * <br><br>
 * <b>Important:</b> VERY expensive to instantiate in terms of memory.
 * <br><br>
 * Contains also some intrinsics static methods for marshalling. 
 *
 * @version     $Revision: 1.9 $
 * @author      Stuart Halloway, http://www.relevancellc.com/halloway/weblog/<br>
 *               Morten Andersen, arosii_moa (at) users.sourceforge.net
 */
public class Variant {

	public static final int SIZEOF = 16;
	
	public int vt;

  public byte                    bVal;                 // VT_UI1.
  public short                   iVal;                 // VT_I2.
  public int                    lVal;                 // VT_I4.
  public float                   fltVal;               // VT_R4.
  public double                  dblVal;               // VT_R8.
  public boolean            boolVal;              // VT_BOOL.
  public int                   scode;                // VT_ERROR.
  public long                      cyVal;                // VT_CY.
  public double                    date;                 // VT_DATE. - use the DateUtil's to read/write this
  public String                    bstrVal;              // VT_BSTR.
      //  public DECIMAL                 [] pdecVal          // VT_BYREF|VT_DECIMAL.
  public IUnknown                 punkVal;         // VT_UNKNOWN.
  public DispatchPtr              pdispVal;        // VT_DISPATCH.
  public SAFEARRAY[]                parray;          // VT_ARRAY|*.
  public byte[]                     pbVal;           // VT_BYREF|VT_UI1.
  public short[]                    piVal;           // VT_BYREF|VT_I2.
  public int[]                     plVal;           // VT_BYREF|VT_I4.
  public float[]                    pfltVal;         // VT_BYREF|VT_R4.
  public double[]                   pdblVal;         // VT_BYREF|VT_R8.
  public boolean[]             pboolVal;        // VT_BYREF|VT_BOOL.
  public int[]                    pscode;          // VT_BYREF|VT_ERROR.
  public long[]                       pcyVal;          // VT_BYREF|VT_CY.
  public double[]                     pdate;           // VT_BYREF|VT_DATE.
  public String pbstrVal;        // VT_BYREF|VT_BSTR.
  public IUnknown[]                 ppunkVal;   // VT_BYREF|VT_UNKNOWN.
  public DispatchPtr[]                ppdispVal;  // VT_BYREF|VT_DISPATCH.
  public SAFEARRAY[][]                pparray;    // VT_ARRAY|*.
  public Variant[]                  pvarVal;         // VT_BYREF|VT_VARIANT.
  public COMPtr                   byref;           // Generic ByRef.
  public byte                    cVal;                 // VT_I1.
  public short          uiVal;                // VT_UI2.
  public int           ulVal;                // VT_UI4.
  public int                     intVal;               // VT_INT.
  public int            uintVal;              // VT_UINT.
  public byte[]              pcVal;                // VT_BYREF|VT_I1.
  public short[]    puiVal;               // VT_BYREF|VT_UI2.
  public int[]     pulVal;               // VT_BYREF|VT_UI4.
  public int[]               pintVal;              // VT_BYREF|VT_INT.
  public int[]      puintVal;             //VT_BYREF|VT_UINT.
  public long		llVal;		// VT_I8
  public long		ullVal;		// VT_UI8

	/**
	 * placeholder class for <code>VT_BYREF</code> objects (mostly [out] or [in, out]-parameters).
	 * Any object that should be marshalled as a <code>VT_BYREF|*<code>-type 
	 * should be wrapped in a ByrefHolder-object before being passed to 
	 * {@link Variant#writeObject(Object, LittleEndianOutputStream) writeObject()}.
	 * <br><br>
	 * If one of the {@link DispatchPtr#invokeN(String, Object[]) DispatchPtr.invoke()}
	 * methods are used, the result will automatically be marshalled into the ByrefHolder
	 * object when the invoke call returns. The caller could then retrive the
	 * result by calling {@link #getRef()}.
	 *
	 * @version     $Revision: 1.9 $
	 * @author      Morten Andersen, arosii_moa (at) users.sourceforge.net
	 */
	public static class ByrefHolder {
		private Object ref;
		
		/**
		 * construct a ByrefHolder holding a reference to the
		 * ref object. Please notice that to be marshalled into the
		 * correct VT-type, one must supply an object of the correct type
		 * (even if it is only an [out]-parameter).
		 * <br><br>
		 * Eg. if calling a method with a signature like:
		 * <pre>	[out]SAFEARRAY(int) *pLongArray</pre>
		 * one should create a ByrefHolder like:
		 * <pre>	ByrefHolder holder = new ByrefHolder(new int[0]);</pre>
		 * 
		 * @param ref the object to marshal as a <code>VT_BYREF|*</code>-type.
		 * 			If <code>null</code> the ByrefHolder will be marshalled
		 * 			as <code>VT_NULL</code>.
		 */
		public ByrefHolder(Object ref) {
			this.ref = ref;
		}
		
		/**
		 * return the referenced object.
		 */
		public Object getRef() {
			return ref;
		}
		
		/**
		 * set the referenced object.
		 */
		public void setRef(Object ref) {
			this.ref = ref;
		}
	}

	/**
	 * marshall an object onto an output stream. The object will be marshalled
	 * following these rules (please notice that primitive types should be 
	 * wrapped in their wrapper types, eg. <code>int</code> should be <code>Integer</code> -
	 * this should not usually be done for arrays though, see below):
	 * <ul>
	 * 	<li><b><code>null</code>:</b> will be marshalled to <code>VT_NULL</code></li>
	 * 	<li><b><code>instanceof {@link ByrefHolder}</code>:</b> will be marshalled
	 * 			as the base type + <code>VT_BYREF</code>.</li>
	 * 	<li><b>array-types:</b> will be marshalled as the base type
	 * 			+ <code>VT_ARRAY</code> (and <code>VT_BYREF</code> if 
	 * 			the array was wrapped in a {@link ByrefHolder}).</li>
	 * 	<li><b><code>Byte</code>:</b> will be marshalled as <code>VT_UI1</code>.</li>
	 * 	<li><b><code>Short</code>:</b> will be marshalled as <code>VT_I2</code>.</li>
	 * 	<li><b><code>Integer</code>:</b> will be marshalled as <code>VT_I4</code>.</li>
	 * 	<li><b><code>Long</code>:</b> will be marshalled as <code>VT_I8</code>.</li>
	 * 	<li><b><code>Float</code>:</b> will be marshalled as <code>VT_R4</code>.</li>    
	 * 	<li><b><code>Double</code>:</b> will be marshalled as <code>VT_R8</code>.</li>
	 * 	<li><b><code>instanceof Date</code>:</b> will be marshalled as <code>VT_DATE</code> and
	 * 			will be converted using {@link DateUtil#getWin32Date(java.util.Date)}.</li>
	 * 	<li><b><code>Boolean</code>:</b> will be marshalled as <code>VT_BOOL</code>.</li>
	 * 	<li><b><code>String</code>:</b> will be marshalled as <code>VT_BSTR</code>.</li>
	 * 	<li><b><code>instanceof {@link Variant}</code>:</b> will be marshalled as a <code>VT_VARIANT</code> using
	 * 			the value of the {@link #vt}-property. Please note that <code>VT_VARIANT</code>
	 * 			MUST be combined with <code>VT_BYREF</code>.</li>
	 * 	<li><b><code>instanceof {@link DispatchPtr}</code>:</b> will be marshalled as 
	 * 			<code>VT_DISPATCH</code>.</li>      
	 * 	<li><b><code>instanceof {@link UnknownPtr}</code>:</b> will be marshalled as 
	 * 			<code>VT_UNKNOWN</code>.</li>      
	 * </ul>
	 * If none of the rules match, a COMException will be thrown.
	 * <br><br>
	 * Notice that the IDispatch coercion mechanism handles scenarios where the
	 * <code>VT_TYPE</code> of the parameters is a not a 100% fit to a method
	 * signature. Therefore there should not be any problems by calling eg. a
	 * method requering <code>unsigned int's</code> with either a Long or an Integer.
	 * <br><br>
	 * <b>Arrays:</b> If writing an array, the primitive types should generally be used
	 * and not the wrapper classes. Eg.
	 * <pre>	var = new int[]{ 7, 9, 13 };</pre>
	 * is correct, whereas
	 * <pre>	var = new Integer[]{ new Integer(7) , new Integer(9) , new Integer(13) };</pre>
	 * is not.
	 * <br><br>
	 * One should consult the section on array-marshalling in docs/jawinuserguide_dispatch.html
	 * for how the different Java-arrays are marshalled.
	 * <br><br>
	 * Arrays of objects will be written as an <code>VT_VARIANT|VT_ARRAY</code> where
	 * each element will be written following the rules mentioned above.
	 * <br><br>
	 * For this reason it is also believed that multidimensional arrays will be
	 * marshalled into a SafeArray on the native side containing other SafeArrays
	 * and NOT multidimensional SafeArrays (TODO: This has not been tested and
	 * should be verified, and perhaps the code should be instrumentable, so it
	 * can be controlled to map multidimensional java-arrays into multimensional SafeArrays
	 * on the native side).
	 * <br><br>
	 * The marshalling code is the "inverse" of the native code in the method
	 * deserializeVariant() in Transform.cpp
	 * 
	 * @param var the object to write to the stream.
	 * @param leos the stream the object should be written to.
	 * @throws COMException if the object can not be marshalled due to
	 * 			invalid type or due to IOExceptions on the stream.
	 */
	public static void writeObject(Object var, LittleEndianOutputStream leos) throws COMException {
		int appendVt = 0;
		try {
			if (var == null) {
				leos.writeShort(VarTypes.VT_NULL);
				return;
			}
			
			if (var instanceof ByrefHolder) {
				var = ((ByrefHolder)var).ref;
				if (var == null) {
					leos.writeShort(VarTypes.VT_NULL);
					return;
				}
				appendVt = VarTypes.VT_BYREF;
			}
			
			Class cls = var.getClass();
			if (cls.isArray()) {
				writeArray(var, appendVt, leos);
				return;
			}

			if (cls == Byte.class) {
				leos.writeShort(VarTypes.VT_UI1 | appendVt);
				leos.writeByte(((Byte)var).byteValue());
			} else if (cls == Short.class) {
				leos.writeShort(VarTypes.VT_I2 | appendVt);
				leos.writeShort(((Short) var).shortValue());
			} else if (cls == Integer.class) {
				leos.writeShort(VarTypes.VT_I4 | appendVt);
				leos.writeInt(((Integer) var).intValue());
			} else if (cls == Long.class) {
				leos.writeShort(VarTypes.VT_I8 | appendVt);
				leos.writeLong(((Long) var).longValue());
			} else if (cls == Float.class) {
				leos.writeShort(VarTypes.VT_R4 | appendVt);
				leos.writeFloat(((Float) var).floatValue());
			} else if (cls == Double.class) {
				leos.writeShort(VarTypes.VT_R8 | appendVt);
				leos.writeDouble(((Double) var).doubleValue());
			} else if (var instanceof Date) {
				leos.writeShort(VarTypes.VT_DATE | appendVt);
				leos.writeDouble(DateUtil.getWin32Date((Date) var));
			} else if (cls == Boolean.class) {
				leos.writeShort(VarTypes.VT_BOOL | appendVt);
				leos.writeBoolean(((Boolean) var).booleanValue());
			} else if (cls == String.class) {
				leos.writeShort(VarTypes.VT_BSTR | appendVt);
				leos.writeStringUnicode((String) var);
			} else if (var instanceof Variant) {
				leos.writeShort(VarTypes.VT_VARIANT | appendVt);
				writeVariant((Variant) var, leos);
			} else if (var instanceof DispatchPtr) {
				leos.writeShort(VarTypes.VT_DISPATCH | appendVt);
				DispatchPtr dp = (DispatchPtr) var;
				leos.writeInt(DispatchPtr.IID_TOKEN);
				leos.writeInt(dp.getPeer());
				leos.writeInt(dp.getUnknown());
			} else if (var instanceof UnknownPtr) {
				leos.writeShort(VarTypes.VT_UNKNOWN | appendVt);
				UnknownPtr up = (UnknownPtr)var;
				leos.writeInt(UnknownPtr.IID_TOKEN);
				leos.writeInt(up.getPeer());
				leos.writeInt(up.getUnknown());
			} else {
				throw new COMException("Type cannot be marshalled to variant: " + cls);
			}
		} catch (IOException ioe) {
			throw new COMException(ioe);
		}
	}

	private static void writeVariant(Variant var, LittleEndianOutputStream leos) throws COMException, IOException {
		leos.writeShort(var.vt);
		switch (var.vt) {
			// the 1 byte integral types
			case VarTypes.VT_I1:
				leos.writeByte(var.cVal);
				break;
			case VarTypes.VT_UI1:
				leos.writeByte(var.bVal);
				break;
			// the 2 byte integral types
			case VarTypes.VT_I2:
				leos.writeShort(var.iVal);
				break;
			case VarTypes.VT_UI2:
				leos.writeShort(var.uiVal);
				break;
			// the 4 byte integral types
			case VarTypes.VT_I4:
				leos.writeInt(var.lVal);
				break;
			case VarTypes.VT_UI4:
				leos.writeInt(var.ulVal);
				break;
			case VarTypes.VT_INT:
				leos.writeInt(var.intVal);
				break;
			case VarTypes.VT_UINT:
				leos.writeInt(var.uintVal);
				break;
			// the 8 byte integral types
			case VarTypes.VT_I8:
				leos.writeLong(var.llVal);
				break;
			case VarTypes.VT_UI8:
				leos.writeLong(var.ullVal);
				break;
			case VarTypes.VT_CY:
				leos.writeLong(var.cyVal);
			// the 4 byte float types
			case VarTypes.VT_R4:
				leos.writeFloat(var.fltVal);
				break;
			// the 4 byte double types
			case VarTypes.VT_R8:
				leos.writeDouble(var.dblVal);
				break;
			case VarTypes.VT_DATE:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -