All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.jna.platform.win32.COM.util.ObjectFactory Maven / Gradle / Ivy

There is a newer version: 1.49.0
Show newest version
/* Copyright (c) 2014 Dr David H. Akehurst (itemis), All Rights Reserved
 *
 * The contents of this file is dual-licensed under 2
 * alternative Open Source/Free licenses: LGPL 2.1 or later and
 * Apache License 2.0. (starting with JNA version 4.0.0).
 *
 * You can freely decide which license you want to apply to
 * the project.
 *
 * You may obtain a copy of the LGPL License at:
 *
 * http://www.gnu.org/licenses/licenses.html
 *
 * A copy is also included in the downloadable source code package
 * containing JNA, in file "LGPL2.1".
 *
 * You may obtain a copy of the Apache License at:
 *
 * http://www.apache.org/licenses/
 *
 * A copy is also included in the downloadable source code package
 * containing JNA, in file "AL2.0".
 */
package com.sun.jna.platform.win32.COM.util;

import java.lang.reflect.Proxy;

import com.sun.jna.platform.win32.Guid.CLSID;
import com.sun.jna.platform.win32.Guid.GUID;
import com.sun.jna.platform.win32.Ole32;
import com.sun.jna.platform.win32.OleAuto;
import com.sun.jna.platform.win32.WTypes;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.WinNT;
import com.sun.jna.platform.win32.COM.COMException;
import com.sun.jna.platform.win32.COM.COMUtils;
import com.sun.jna.platform.win32.COM.Dispatch;
import com.sun.jna.platform.win32.COM.IDispatch;
import com.sun.jna.platform.win32.COM.IDispatchCallback;
import com.sun.jna.platform.win32.COM.util.annotation.ComObject;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.WinDef.LCID;
import com.sun.jna.platform.win32.WinNT.HRESULT;
import com.sun.jna.ptr.PointerByReference;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

/**
 * Factory keeps track of COM objects - all objects created with this factory
 * can be disposed by calling {@link Factory#disposeAll() }.
 */
public class ObjectFactory {

    @Override
    protected void finalize() throws Throwable {
        try {
            this.disposeAll();
        } finally {
            super.finalize();
        }
    }

    /**
     * CoInitialize must be called be fore this method. Either explicitly or
     * implicitly via other methods.
     *
     * @return running object table
     */
    public IRunningObjectTable getRunningObjectTable() {
        assert COMUtils.comIsInitialized() : "COM not initialized";

        final PointerByReference rotPtr = new PointerByReference();

        HRESULT hr = Ole32.INSTANCE.GetRunningObjectTable(new WinDef.DWORD(0), rotPtr);

        COMUtils.checkRC(hr);
        com.sun.jna.platform.win32.COM.RunningObjectTable raw = new com.sun.jna.platform.win32.COM.RunningObjectTable(
            rotPtr.getValue());
        IRunningObjectTable rot = new RunningObjectTable(raw, this);
        return rot;
    }

    /**
     * Creates a ProxyObject for the given interface and IDispatch pointer.
     * 

*/ public T createProxy(Class comInterface, IDispatch dispatch) { assert COMUtils.comIsInitialized() : "COM not initialized"; ProxyObject jop = new ProxyObject(comInterface, dispatch, this); Object proxy = Proxy.newProxyInstance(comInterface.getClassLoader(), new Class[]{comInterface}, jop); T result = comInterface.cast(proxy); return result; } /** * Creates a new COM object (CoCreateInstance) for the given progId and * returns a ProxyObject for the given interface. */ public T createObject(Class comInterface) { assert COMUtils.comIsInitialized() : "COM not initialized"; ComObject comObectAnnotation = comInterface.getAnnotation(ComObject.class); if (null == comObectAnnotation) { throw new COMException( "createObject: Interface must define a value for either clsId or progId via the ComInterface annotation"); } final GUID guid = this.discoverClsId(comObectAnnotation); final PointerByReference ptrDisp = new PointerByReference(); WinNT.HRESULT hr = Ole32.INSTANCE.CoCreateInstance(guid, null, WTypes.CLSCTX_SERVER, IDispatch.IID_IDISPATCH, ptrDisp); COMUtils.checkRC(hr); Dispatch d = new Dispatch(ptrDisp.getValue()); T t = this.createProxy(comInterface, d); //CoCreateInstance returns a pointer to COM object with a +1 reference count, so we must drop one //Note: the createProxy adds one int n = d.Release(); return t; } /** * Gets and existing COM object (GetActiveObject) for the given progId and * returns a ProxyObject for the given interface. */ public T fetchObject(Class comInterface) throws COMException { assert COMUtils.comIsInitialized() : "COM not initialized"; ComObject comObectAnnotation = comInterface.getAnnotation(ComObject.class); if (null == comObectAnnotation) { throw new COMException( "createObject: Interface must define a value for either clsId or progId via the ComInterface annotation"); } final GUID guid = this.discoverClsId(comObectAnnotation); final PointerByReference ptrDisp = new PointerByReference(); WinNT.HRESULT hr = OleAuto.INSTANCE.GetActiveObject(guid, null, ptrDisp); COMUtils.checkRC(hr); Dispatch d = new Dispatch(ptrDisp.getValue()); T t = this.createProxy(comInterface, d); //GetActiveObject returns a pointer to COM object with a +1 reference count, so we must drop one //Note: the createProxy adds one d.Release(); return t; } GUID discoverClsId(ComObject annotation) { assert COMUtils.comIsInitialized() : "COM not initialized"; String clsIdStr = annotation.clsId(); final String progIdStr = annotation.progId(); if (null != clsIdStr && !clsIdStr.isEmpty()) { return new CLSID(clsIdStr); } else if (null != progIdStr && !progIdStr.isEmpty()) { final CLSID.ByReference rclsid = new CLSID.ByReference(); WinNT.HRESULT hr = Ole32.INSTANCE.CLSIDFromProgID(progIdStr, rclsid); COMUtils.checkRC(hr); return rclsid; } else { throw new COMException("ComObject must define a value for either clsId or progId"); } } IDispatchCallback createDispatchCallback(Class comEventCallbackInterface, IComEventCallbackListener comEventCallbackListener) { return new CallbackProxy(this, comEventCallbackInterface, comEventCallbackListener); } // Proxy object release their COM interface reference latest in the // finalize method, which is run when garbadge collection removes the // object. // When the factory is finished, the referenced objects loose their // environment and can't be used anymore. registeredObjects is used // to dispose interfaces even if garbadge collection has not yet collected // the proxy objects. private final List> registeredObjects = new LinkedList>(); public void register(ProxyObject proxyObject) { synchronized (this.registeredObjects) { this.registeredObjects.add(new WeakReference(proxyObject)); } } public void unregister(ProxyObject proxyObject) { synchronized (this.registeredObjects) { Iterator> iterator = this.registeredObjects.iterator(); while (iterator.hasNext()) { WeakReference weakRef = iterator.next(); ProxyObject po = weakRef.get(); if (po == null || po == proxyObject) { iterator.remove(); } } } } public void disposeAll() { synchronized (this.registeredObjects) { List> s = new ArrayList>(this.registeredObjects); for (WeakReference weakRef : s) { ProxyObject po = weakRef.get(); if (po != null) { po.dispose(); } } this.registeredObjects.clear(); } } /** * The Constant LOCALE_USER_DEFAULT. */ private final static LCID LOCALE_USER_DEFAULT = Kernel32.INSTANCE.GetUserDefaultLCID(); private LCID LCID; /** * Retrieve the LCID to be used for COM calls. * * @return If {@code setLCID} is not called retrieves the users default * locale, else the set LCID. */ public LCID getLCID() { if (LCID != null) { return LCID; } else { return LOCALE_USER_DEFAULT; } } /** * Set the LCID to use for COM calls. * * @param value override LCID. NULL resets to default. */ public void setLCID(LCID value) { LCID = value; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy