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

📄 identitymanager.java

📁 java 调用windows的api
💻 JAVA
字号:
/*
 * IdentityManager.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: IdentityManager.java,v 1.5 2005/03/14 19:38:20 arosii_moa Exp $ */

package org.jawin;

import java.io.IOException;
import java.util.HashMap;

import org.jawin.io.LittleEndianInputStream;
import org.jawin.io.LittleEndianOutputStream;
import org.jawin.io.NakedByteStream;
import org.jawin.marshal.StructConverter;

/**
 * 
 *
 * @version     $Revision: 1.5 $
 * @author      Stuart Halloway, http://www.relevancellc.com/halloway/weblog/
 */
public class IdentityManager {

	/**
	 * If the property <code>org.jawin.traceRefs</code> is set the
	 * reference counting for COM objects will be traced on <code>System.out</code>.
	 */
	public static final boolean TRACE_REFS = 
		(null != System.getProperty("org.jawin.traceRefs"));

	/**
	 * a map used for storing the reference counts for GIT cookies as
	 * peer-Integers -> {@link Identity}-objects.
	 * 
	 * Any changes to this map should be synchronized around the map itself, like:
	 * <pre>
	 * 	synchronized(idents) {
	 * 		do work
	 *  }
	 * </pre>
	 */
	private static final HashMap idents = new HashMap();
	
	/**
	 * a map used for storing GUID to class mappings for all registered
	 * proxies (see {@link #registerProxy(GUID, Class)}. Maps
	 * GUID -> Class for proxy.
	 */
	private static final HashMap guidToClass = new HashMap();

	/**
	 * private constructor to avoid instantiation, as this class only contains
	 * static methods.
	 */
	private IdentityManager() {
		// never called
	}


	static COMPtr queryInterface(Class newItf, COMPtr src) throws COMException {
		return queryInterface(newCOMPtr(newItf), src);
	}

	static COMPtr queryInterface(COMPtr dest, COMPtr src) throws COMException {
		return getDirectRef(dest, src, true);
	}

	static COMPtr queryGITInterface(Class newItf, COMPtr src) throws COMException {
		return getGITRef(newCOMPtr(newItf), src, true);
	}

	static COMPtr createDirectRef(COMPtr src) throws COMException {
		return getDirectRef(newCOMPtr(src.getClass()), src, false);
	}

	static COMPtr createGITRef(COMPtr src) throws COMException {
		return getGITRef(newCOMPtr(src.getClass()), src, false);
	}

	private static COMPtr newCOMPtr(Class template) {
		try {
			return (COMPtr)template.newInstance();
		} catch (Exception e) {
			throw new COMError("Unable to create instance of " + template.getClass());
		}
	}

	/**
	 * to retrieve a non-thread safe interface reference.
	 * 
	 * @param dest the destination to init to a direct ref.
	 * @param src the source to retrieve the direct ref from.
	 * @param destIf if true, it is a queryInterface on the dest object. If false
	 * 			a copy of the src interface is requested (and the dest and src 
	 * 			should be equal).
	 * @return the dest object.
	 */
	private static COMPtr getDirectRef(COMPtr dest, COMPtr src, boolean destIf) throws COMException {
		synchronized (src) {
			int unknown = src.getUnknown();
			if (unknown != 0) {
				// the src is a direct ref.
				if (destIf) {
					// query interface - the queryInterface calls AddRef so we set
					// the unknown pointer the "dirty" way.
					dest.setUnknown(Bootstrap.queryInterface(unknown, dest.getIIDToken()));
				} else {
					dest.copyUnknown(src);
				}
			} else {
				// the src is a GIT ref, and should be unmarshalled as a src interface
				int gitUnknown = Bootstrap.unmarshalFromGIT(src.getPeer(), src.getIIDToken());
				if (destIf) {
					dest.setUnknown(Bootstrap.queryInterface(gitUnknown, dest.getIIDToken()));
					// and the release the gitUnknown again
					Bootstrap.directCOM(gitUnknown, 2); // vtable index 2 is Release in IUnknown
				} else {
					// we take over the gitUnknown, so no reason to call release
					dest.setUnknown(gitUnknown);
				}
			}
		}
		if (TRACE_REFS) {
			System.out.println(src + (destIf ? " QI --> " : " unmarshal --> ") + dest);
		}
		return dest;
	}

	/**
	 * * to retrieve a thread safe interface reference.
	 * 
	 * @param dest the destination to init to a GIT reference.
	 * @param src the source to retrieve the reference from.
	 * @param destIf if true, it is a queryInterface on the dest object. If false
	 * 			a copy of the src interface is requested (and the dest and src 
	 * 			should be equal).
	 * @return the dest object.
	 */
	private static COMPtr getGITRef(COMPtr dest, COMPtr src, boolean destIf) throws COMException {
		int peer;
		synchronized (src) {
			peer = src.getPeer();
			if (peer == 0) {
				// the src is a direct ref.
				if (destIf) {
					// query interface - the queryInterface calls AddRef so we have
					// to release it again after marshalling to a GIT cookie
					int unknown = Bootstrap.queryInterface(src.getUnknown(), dest.getIIDToken());
					peer = Bootstrap.marshalToGIT(unknown, dest.getIIDToken());
					// release the interface again - FIXME - should we do this?
					Bootstrap.directCOM(unknown, 2); // vtable index 2 is Release in IUnknown
				} else {
					peer = Bootstrap.marshalToGIT(src.getUnknown(), src.getIIDToken());
				}
			} else {
				if (destIf) {
					// we have to unmarshal as a src interface from GIT,
					// query the dest interface, marshal this to a dest GIT
					// and finally call release on both the unmarshalled src interface
					// and the queried dest interface.
					int unknown = Bootstrap.unmarshalFromGIT(peer, src.getIIDToken());
					int destUnknown = Bootstrap.queryInterface(unknown, dest.getIIDToken());
					peer = Bootstrap.marshalToGIT(destUnknown, dest.getIIDToken());
					// release all the interfaces again - FIXME - should we do this?
					Bootstrap.directCOM(destUnknown, 2); // vtable index 2 is Release in IUnknown
					Bootstrap.directCOM(unknown, 2);
				}
			}
		}
		dest.setPeer(peer);
		return dest;
	}

	/** 
	 * increments the cached ref count for the proxy.  If identity
	 * does not exist yet, create it.
	 */
	static Identity incRef(int peer) {
		Integer key = new Integer(peer);
		synchronized (idents) {
			Identity i = (Identity) idents.get(key);
			if (i == null) {
				i = new Identity(peer);
				idents.put(key, i);
			} else {
				i.incRef();
			}
			return i;
		}
	}

	/**
	 * decrements the cached ref count for the proxy.  If count 
	 * reaches zero, revoke the GIT pointer
	 */
	static void decRef(int peer) throws COMException {
		int refCount = 0;
		Integer key = new Integer(peer);
		synchronized (idents) {
			Identity i = (Identity) idents.get(key);
			if (i == null) {
				throw new COMError("Peer " + peer + " is not a COM identity");
			}
			refCount = i.decRef();
			if (refCount == 0) {
				idents.remove(key);
			}
		}
		if (refCount == 0) {
			Bootstrap.revokeGIT(peer);
		}
	}
	
	public static COMPtr getCOMPtr(int peer, int unk, GUID iid) {
		Class proxyClass = (Class) guidToClass.get(iid);
		if (proxyClass == null) {
			throw new COMError("No Java class for Interface Identifier: " + iid);
		}
		COMPtr ret = newCOMPtr(proxyClass);
		ret.setUnknown(unk);
		ret.setPeer(peer);
		return ret;
	}

	public static COMPtr getCOMPtr(LittleEndianInputStream leis, GUID iid) throws IOException, COMException {
		int unk = leis.readInt();
		int peer = leis.readInt();
		return getCOMPtr(peer, unk, iid);
	}

	public static COMPtr getCOMPtr(byte[] stream, int offset, GUID iid) throws COMException {
		int unk = StructConverter.bytesIntoInt(stream, offset);
		int peer = StructConverter.bytesIntoInt(stream, offset + 4);
		return getCOMPtr(peer, unk, iid);
	}

	private static void registerProxyPrototype(GUID iid, Class proxy) {
		guidToClass.put(iid, proxy);
	}

	/**
	 * Each COM Interface Identifier (IID) must have a proxy class registered with the system.
	 * See {@link COMPtr} for more information about registering your class.
	 * 
	 * @throws NullPointerException if either iid or proxy is null.
	 * @throws COMError if any error happens during registering the proxy.
	 */
	public static int registerProxy(GUID iid, Class proxy) {
		if ((iid == null) || (proxy == null)) {
			throw new NullPointerException("neither GUID (" + iid + ") or the proxy class (" + proxy + ") can be null");
		}
		
		IdentityManager.registerProxyPrototype(iid, proxy);
		NakedByteStream nbs = new NakedByteStream(GUID.SIZEOF);
		LittleEndianOutputStream leos = new LittleEndianOutputStream(nbs);
		try {
			iid.marshal(leos, null);
			// TODO carefull here we are passing a reference to an 
			// internal datastructure - .length can not be trusted.
			return Bootstrap.registerGUID(nbs.getInternalBuffer());
		} catch (IOException e) {
			throw new COMError("IO-error when registering the GUID '" + iid + "' for class '" + proxy + "' (" + e.getMessage() + ")");
		} catch (COMException e) {
			throw new COMError("Unable to register the GUID '" + iid + "' for class '" + proxy + "' (" + e.getMessage() + ")");
		}
	}
}

⌨️ 快捷键说明

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