Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  helper_purpenv_Proxy.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */



#include "Proxy.hxx"

#include <sal/log.hxx>
#include <uno/dispatcher.h>
#include <typelib/typedescription.hxx>
#include <utility>

using namespace com::sun::star;

static bool relatesToInterface(typelib_TypeDescription * pTypeDescr)
{
    switch (pTypeDescr->eTypeClass)
    {
//      case typelib_TypeClass_TYPEDEF:
    case typelib_TypeClass_SEQUENCE:
    {
        switch (reinterpret_cast<typelib_IndirectTypeDescription *>(pTypeDescr)->pType->eTypeClass)
        {
        case typelib_TypeClass_INTERFACE:
        case typelib_TypeClass_ANY: // might relate to interface
            return true;
        case typelib_TypeClass_SEQUENCE:
        case typelib_TypeClass_STRUCT:
        case typelib_TypeClass_EXCEPTION:
        {
            typelib_TypeDescription * pTD = nullptr;
            TYPELIB_DANGER_GET( &pTD, reinterpret_cast<typelib_IndirectTypeDescription *>(pTypeDescr)->pType );
            bool bRel = relatesToInterface( pTD );
            TYPELIB_DANGER_RELEASE( pTD );
            return bRel;
        }
        default:
            ;
        }
        return false;
    }
    case typelib_TypeClass_STRUCT:
    case typelib_TypeClass_EXCEPTION:
    {
        // ...optimized... to avoid getDescription() calls!
        typelib_CompoundTypeDescription * pComp    = reinterpret_cast<typelib_CompoundTypeDescription *>(pTypeDescr);
        typelib_TypeDescriptionReference ** pTypes = pComp->ppTypeRefs;
        for ( sal_Int32 nPos = pComp->nMembers; nPos--; )
        {
            switch (pTypes[nPos]->eTypeClass)
            {
            case typelib_TypeClass_INTERFACE:
            case typelib_TypeClass_ANY: // might relate to interface
                return true;
//              case typelib_TypeClass_TYPEDEF:
            case typelib_TypeClass_SEQUENCE:
            case typelib_TypeClass_STRUCT:
            case typelib_TypeClass_EXCEPTION:
            {
                typelib_TypeDescription * pTD = nullptr;
                TYPELIB_DANGER_GET( &pTD, pTypes[nPos] );
                bool bRel = relatesToInterface( pTD );
                TYPELIB_DANGER_RELEASE( pTD );
                if (bRel)
                    return true;
                break;
            }
            default:
                break;
            }
        }
        if (pComp->pBaseTypeDescription)
            return relatesToInterface( &pComp->pBaseTypeDescription->aBase );
        break;
    }
    case typelib_TypeClass_ANY: // might relate to interface
    case typelib_TypeClass_INTERFACE:
        return true;

    default:
        ;
    }
    return false;
}

extern "C" { static void s_Proxy_dispatch(
    uno_Interface                 * pUnoI,
    typelib_TypeDescription const * pMemberType,
    void                          * pReturn,
    void                          * pArgs[],
    uno_Any                      ** ppException) noexcept
{
    Proxy * pThis = static_cast<Proxy *>(pUnoI);

    typelib_MethodParameter            param;
    sal_Int32                          nParams = 0;
    typelib_MethodParameter          * pParams = nullptr;
    typelib_TypeDescriptionReference * pReturnTypeRef = nullptr;
    // sal_Int32                          nOutParams = 0;

    switch (pMemberType->eTypeClass)
    {
    case typelib_TypeClass_INTERFACE_ATTRIBUTE:
        if (pReturn)
        {
            pReturnTypeRef =
                reinterpret_cast<typelib_InterfaceAttributeTypeDescription const *>(
                 pMemberType)->pAttributeTypeRef;
            nParams = 0;
            pParams = nullptr;
        }
        else
        {
            param.pTypeRef = reinterpret_cast<typelib_InterfaceAttributeTypeDescription const *>(
                              pMemberType)->pAttributeTypeRef;
            param.bIn = true;
            param.bOut = false;
            nParams = 1;
            pParams = ¶m;
        }
        break;
    case typelib_TypeClass_INTERFACE_METHOD:
    {
        typelib_InterfaceMethodTypeDescription const * method_td =
            reinterpret_cast<typelib_InterfaceMethodTypeDescription const *>(pMemberType);
        pReturnTypeRef = method_td->pReturnTypeRef;
        nParams = method_td->nParams;
        pParams = method_td->pParams;
        break;
    }
    default:
        OSL_FAIL( "### illegal member typeclass!" );
        abort();
    }

    pThis->dispatch( pReturnTypeRef,
                     pParams,
                     nParams,
                     pMemberType,
                     pReturn,
                     pArgs,
                     ppException );
}}

extern "C" void Proxy_free(SAL_UNUSED_PARAMETER uno_ExtEnvironment * /*pEnv*/, void * pProxy) noexcept
{
    Proxy * pThis = static_cast<Proxy * >(static_cast<uno_Interface *>(pProxy));
    delete pThis;
}

extern "C" {
static void s_Proxy_acquire(uno_Interface * pUnoI) noexcept
{
    Proxy * pProxy = static_cast<Proxy *>(pUnoI);
    pProxy->acquire();
}

static void s_Proxy_release(uno_Interface * pUnoI) noexcept
{
    Proxy * pProxy = static_cast<Proxy *>(pUnoI);
    pProxy->release();
}

static void s_acquireAndRegister_v(va_list * pParam)
{
    uno_Interface                    * pUnoI      = va_arg(*pParam, uno_Interface *);
    rtl_uString                      * pOid       = va_arg(*pParam, rtl_uString *);
    typelib_InterfaceTypeDescription * pTypeDescr = va_arg(*pParam, typelib_InterfaceTypeDescription *);
    uno_ExtEnvironment               * pEnv       = va_arg(*pParam, uno_ExtEnvironment *);

    pUnoI->acquire(pUnoI);
    pEnv->registerInterface(pEnv, reinterpret_cast<void **>(&pUnoI), pOid, pTypeDescr);
}
}

Proxy::Proxy(uno::Mapping                          to_from,
             uno_Environment                     * pTo,
             uno_Environment                     * pFrom,
             uno_Interface                       * pUnoI,
             typelib_InterfaceTypeDescription    * pTypeDescr,
             OUString                      const & rOId,
             cppu::helper::purpenv::ProbeFun     * probeFun,
             void                                * pProbeContext
)
        : m_nRef         (1),
          m_from         (pFrom),
          m_to           (pTo),
          m_from_to      (pFrom, pTo),
          m_to_from      (std::move(to_from)),
          m_pUnoI        (pUnoI),
          m_pTypeDescr   (pTypeDescr),
          m_aOId         (rOId),
          m_probeFun     (probeFun),
          m_pProbeContext(pProbeContext)
{
    SAL_INFO("cppu.purpenv""LIFE: Proxy::Proxy(<>) -> " << this);

    typelib_typedescription_acquire(&m_pTypeDescr->aBase);
    if (!m_pTypeDescr->aBase.bComplete)
        typelib_typedescription_complete(reinterpret_cast<typelib_TypeDescription **>(&m_pTypeDescr));

    OSL_ENSURE(m_pTypeDescr->aBase.bComplete, "### type is incomplete!");

    uno_Environment_invoke(m_to.get(), s_acquireAndRegister_v, m_pUnoI, rOId.pData, pTypeDescr, m_to.get());

    // uno_Interface
    uno_Interface::acquire     = s_Proxy_acquire;
    uno_Interface::release     = s_Proxy_release;
    uno_Interface::pDispatcher = s_Proxy_dispatch;
}

extern "C" { static void s_releaseAndRevoke_v(va_list * pParam)
{
    uno_ExtEnvironment * pEnv  = va_arg(*pParam, uno_ExtEnvironment *);
    uno_Interface      * pUnoI = va_arg(*pParam, uno_Interface *);

    pEnv->revokeInterface(pEnv, pUnoI);
    pUnoI->release(pUnoI);
}}

Proxy::~Proxy()
{
    SAL_INFO("cppu.purpenv""LIFE: Proxy::~Proxy() -> " << this);

    uno_Environment_invoke(m_to.get(), s_releaseAndRevoke_v, m_to.get(), m_pUnoI);

    typelib_typedescription_release(&m_pTypeDescr->aBase);
}

static uno::TypeDescription getAcquireMethod()
{
    typelib_TypeDescriptionReference * type_XInterface =
        * typelib_static_type_getByTypeClass(typelib_TypeClass_INTERFACE);

    typelib_TypeDescription * pTXInterfaceDescr = nullptr;
    TYPELIB_DANGER_GET    (&pTXInterfaceDescr, type_XInterface);
    uno::TypeDescription acquire(
        reinterpret_cast< typelib_InterfaceTypeDescription * >(
            pTXInterfaceDescr)->ppAllMembers[1]);
    TYPELIB_DANGER_RELEASE(pTXInterfaceDescr);

    return acquire;
}

static uno::TypeDescription getReleaseMethod()
{
    typelib_TypeDescriptionReference * type_XInterface =
        * typelib_static_type_getByTypeClass(typelib_TypeClass_INTERFACE);

    typelib_TypeDescription * pTXInterfaceDescr = nullptr;
    TYPELIB_DANGER_GET    (&pTXInterfaceDescr, type_XInterface);
    uno::TypeDescription release(
        reinterpret_cast< typelib_InterfaceTypeDescription * >(
            pTXInterfaceDescr)->ppAllMembers[2]);
    TYPELIB_DANGER_RELEASE(pTXInterfaceDescr);

    return release;
}

static uno::TypeDescription s_acquireMethod(getAcquireMethod());
static uno::TypeDescription s_releaseMethod(getReleaseMethod());

void Proxy::acquire()
{
    if (m_probeFun)
        m_probeFun(true,
                   this,
                   m_pProbeContext,
                   *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID),
                   nullptr,
                   0,
                   s_acquireMethod.get(),
                   nullptr,
                   nullptr,
                   nullptr);

    if (osl_atomic_increment(&m_nRef) == 1)
    {
        // rebirth of proxy zombie
        void * pThis = this;
        m_from.get()->pExtEnv->registerProxyInterface(m_from.get()->pExtEnv,
                                                      &pThis,
                                                      Proxy_free,
                                                      m_aOId.pData,
                                                      m_pTypeDescr);
        OSL_ASSERT(pThis == this);
    }

    if (m_probeFun)
        m_probeFun(false,
                   this,
                   m_pProbeContext,
                   *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID),
                   nullptr,
                   0,
                   s_acquireMethod.get(),
                   nullptr,
                   nullptr,
                   nullptr);

}

void Proxy::release()
{
    cppu::helper::purpenv::ProbeFun * probeFun = m_probeFun;
    void                            * pProbeContext = m_pProbeContext;

    if (m_probeFun)
        m_probeFun(true,
                   this,
                   m_pProbeContext,
                   *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID),
                   nullptr,
                   0,
                   s_releaseMethod.get(),
                   nullptr,
                   nullptr,
                   nullptr);

    if (osl_atomic_decrement(&m_nRef) == 0)
        m_from.get()->pExtEnv->revokeInterface(m_from.get()->pExtEnv, this);

    if (probeFun)
        probeFun(false,
                 this,
                 pProbeContext,
                 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID),
                 nullptr,
                 0,
                 s_releaseMethod.get(),
                 nullptr,
                 nullptr,
                 nullptr);

}


extern "C" {
static void s_type_destructData_v(va_list * pParam)
{
    void * ret = va_arg(*pParam, void *);
    typelib_TypeDescriptionReference * pReturnTypeRef = va_arg(*pParam, typelib_TypeDescriptionReference *);

    uno_type_destructData(ret, pReturnTypeRef, nullptr);
}

static void s_dispatcher_v(va_list * pParam)
{
    uno_Interface                 * pUnoI       = va_arg(*pParam, uno_Interface *);
    typelib_TypeDescription const * pMemberType = va_arg(*pParam, typelib_TypeDescription const *);
    void                          * pReturn     = va_arg(*pParam, void *);
    void                         ** pArgs       = va_arg(*pParam, void **);
    uno_Any                      ** ppException = va_arg(*pParam, uno_Any **);

    pUnoI->pDispatcher(pUnoI, pMemberType, pReturn, pArgs, ppException);
}
}

void Proxy::dispatch(typelib_TypeDescriptionReference * pReturnTypeRef,
                     typelib_MethodParameter          * pParams,
                     sal_Int32                          nParams,
                     typelib_TypeDescription    const * pMemberType,
                     void                             * pReturn,
                     void                             * pArgs[],
                     uno_Any                         ** ppException)
{
    if (m_probeFun)
        m_probeFun(true,
                   this,
                   m_pProbeContext,
                   pReturnTypeRef,
                   pParams,
                   nParams,
                   pMemberType,
                   pReturn,
                   pArgs,
                   ppException);

    void ** args = static_cast<void **>(alloca( sizeof (void *) * nParams ));

    typelib_TypeDescription * return_td = nullptr;
    void * ret = pReturn;
    if (pReturnTypeRef)
    {
        TYPELIB_DANGER_GET(&return_td, pReturnTypeRef);

        if (relatesToInterface(return_td))
            ret = alloca(return_td->nSize);

        TYPELIB_DANGER_RELEASE(return_td);
    }

    for (sal_Int32 nPos = 0; nPos < nParams; ++ nPos)
    {
        typelib_MethodParameter const & param = pParams[nPos];
        typelib_TypeDescription * td = nullptr;
        TYPELIB_DANGER_GET( &td, param.pTypeRef );
        if (relatesToInterface(td))
        {
            args[nPos] = alloca(td->nSize);
            if (param.bIn)
            {
                uno_copyAndConvertData(args[nPos], pArgs[nPos], td, m_from_to.get());
            }
        }
        else
        {
            args[nPos] = pArgs[nPos];
        }
        TYPELIB_DANGER_RELEASE( td );
    }

    uno_Any exc_data;
    uno_Any * exc = &exc_data;

    // do the UNO call...
    uno_Environment_invoke(m_to.get(), s_dispatcher_v, m_pUnoI, pMemberType, ret, args, &exc);

    if (exc == nullptr)
    {
        for (sal_Int32 nPos = 0; nPos < nParams; ++ nPos)
        {
            if (args[nPos] != pArgs[nPos])
            {
                typelib_MethodParameter const & param = pParams[nPos];
                if (param.bOut)
                {
                    if (param.bIn) // is inout
                    {
                        uno_type_destructData(pArgs[nPos], param.pTypeRef, nullptr);
                    }
                    uno_type_copyAndConvertData(pArgs[ nPos ],
                                                args[ nPos ],
                                                param.pTypeRef,
                                                m_to_from.get());
                }
                uno_Environment_invoke(m_to.get(), s_type_destructData_v, args[nPos], param.pTypeRef, 0);
            }
        }
        if (ret != pReturn)
        {
            uno_type_copyAndConvertData(pReturn,
                                        ret,
                                        pReturnTypeRef,
                                        m_to_from.get());

            uno_Environment_invoke(m_to.get(), s_type_destructData_v, ret, pReturnTypeRef, 0);
        }

        *ppException = nullptr;
    }
    else // exception occurred
    {
        for (sal_Int32 nPos = 0; nPos < nParams; ++ nPos)
        {
            if (args[nPos] != pArgs[nPos])
            {
                typelib_MethodParameter const & param = pParams[nPos];
                if (param.bIn)
                {
                    uno_Environment_invoke(m_to.get(), s_type_destructData_v, args[nPos], param.pTypeRef, 0);
                }
            }
        }

        uno_type_any_constructAndConvert(*ppException,
                                         exc->pData,
                                         exc->pType,
                                         m_to_from.get());

        // FIXME: need to destruct in m_to
        uno_any_destruct(exc, nullptr);
    }

    if (m_probeFun)
        m_probeFun(false,
                   this,
                   m_pProbeContext,
                   pReturnTypeRef,
                   pParams,
                   nParams,
                   pMemberType,
                   pReturn,
                   pArgs,
                   ppException);
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=89 H=95 G=91

¤ Dauer der Verarbeitung: 0.7 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge