[Libreoffice-commits] core.git: pyuno/source stoc/source

Matthew J. Francis mjay.francis at gmail.com
Mon Jul 27 00:41:07 PDT 2015


 pyuno/source/module/pyuno.cxx         |   95 +++++++---------
 pyuno/source/module/pyuno_adapter.cxx |   27 ++++
 pyuno/source/module/pyuno_impl.hxx    |    9 -
 pyuno/source/module/pyuno_module.cxx  |    4 
 pyuno/source/module/pyuno_runtime.cxx |   22 +--
 stoc/source/inspect/introspection.cxx |  193 ++++++++++++++++++++++++++++------
 stoc/source/invocation/invocation.cxx |   50 +++++++-
 7 files changed, 288 insertions(+), 112 deletions(-)

New commits:
commit 9c5a217681935d661aad4d5667a775319382d22a
Author: Matthew J. Francis <mjay.francis at gmail.com>
Date:   Thu Jul 23 11:36:38 2015 +0800

    Tweak introspection/invocation to be more useful to PyUNO
    
    - Make introspection/invocation handle XNameReplace and
      XIndexReplace
    - Make introspection handle XUnoTunnel
    - Adapt PyUNO to take advantage of the additionally handled
      interfaces
    
    Change-Id: Ie848d10fd2c31cad76fcc3a746262a490a2c9ae1
    Reviewed-on: https://gerrit.libreoffice.org/17314
    Reviewed-by: Matthew Francis <mjay.francis at gmail.com>
    Tested-by: Matthew Francis <mjay.francis at gmail.com>

diff --git a/pyuno/source/module/pyuno.cxx b/pyuno/source/module/pyuno.cxx
index f068961..ccab344 100644
--- a/pyuno/source/module/pyuno.cxx
+++ b/pyuno/source/module/pyuno.cxx
@@ -60,6 +60,7 @@ using com::sun::star::uno::XComponentContext;
 using com::sun::star::lang::XSingleServiceFactory;
 using com::sun::star::lang::XServiceInfo;
 using com::sun::star::lang::XTypeProvider;
+using com::sun::star::lang::XUnoTunnel;
 using com::sun::star::script::XTypeConverter;
 using com::sun::star::script::XInvocation2;
 using com::sun::star::beans::XMaterialHolder;
@@ -563,7 +564,7 @@ sal_Int32 lcl_detach_getLength( PyUNO *me )
     // returned by getElementNames(), or the user may be surprised.
 
     // For XIndexContainer
-    Reference< XIndexAccess > xIndexAccess( me->members->wrappedObject, UNO_QUERY );
+    Reference< XIndexAccess > xIndexAccess( me->members->xInvocation, UNO_QUERY );
     if ( xIndexAccess.is() )
     {
         return xIndexAccess->getCount();
@@ -571,7 +572,7 @@ sal_Int32 lcl_detach_getLength( PyUNO *me )
 
     // For XNameContainer
     // Not terribly efficient - get the count of all the names
-    Reference< XNameAccess > xNameAccess( me->members->wrappedObject, UNO_QUERY );
+    Reference< XNameAccess > xNameAccess( me->members->xInvocation, UNO_QUERY );
     if ( xNameAccess.is() )
     {
         return xNameAccess->getElementNames().getLength();
@@ -782,7 +783,7 @@ PyObject* lcl_getitem_index( PyUNO *me, PyObject *pKey, Runtime& runtime )
     {
         PyThreadDetach antiguard;
 
-        Reference< XIndexAccess > xIndexAccess( me->members->wrappedObject, UNO_QUERY );
+        Reference< XIndexAccess > xIndexAccess( me->members->xInvocation, UNO_QUERY );
         if ( xIndexAccess.is() )
         {
             if (nIndex < 0)
@@ -809,7 +810,7 @@ PyObject* lcl_getitem_slice( PyUNO *me, PyObject *pKey )
     {
         PyThreadDetach antiguard;
 
-        xIndexAccess.set( me->members->wrappedObject, UNO_QUERY );
+        xIndexAccess.set( me->members->xInvocation, UNO_QUERY );
         if ( xIndexAccess.is() )
             nLen = xIndexAccess->getCount();
     }
@@ -850,7 +851,7 @@ PyObject* lcl_getitem_string( PyUNO *me, PyObject *pKey, Runtime& runtime )
     {
         PyThreadDetach antiguard;
 
-        Reference< XNameAccess > xNameAccess( me->members->wrappedObject, UNO_QUERY );
+        Reference< XNameAccess > xNameAccess( me->members->xInvocation, UNO_QUERY );
         if ( xNameAccess.is() )
         {
             aRet = xNameAccess->getByName( sKey );
@@ -914,8 +915,8 @@ PyObject* PyUNO_getitem( PyObject *self, PyObject *pKey )
         // If the object is an XIndexAccess and/or XNameAccess, but the
         // key passed wasn't suitable, give a TypeError which specifically
         // describes this
-        Reference< XIndexAccess > xIndexAccess( me->members->wrappedObject, UNO_QUERY );
-        Reference< XNameAccess > xNameAccess( me->members->wrappedObject, UNO_QUERY );
+        Reference< XIndexAccess > xIndexAccess( me->members->xInvocation, UNO_QUERY );
+        Reference< XNameAccess > xNameAccess( me->members->xInvocation, UNO_QUERY );
         if ( xIndexAccess.is() || xNameAccess.is() )
         {
             PyErr_SetString( PyExc_TypeError, "subscription with invalid type" );
@@ -985,11 +986,11 @@ int lcl_setitem_index( PyUNO *me, PyObject *pKey, PyObject *pValue )
     {
         PyThreadDetach antiguard;
 
-        xIndexContainer.set( me->members->wrappedObject, UNO_QUERY );
+        xIndexContainer.set( me->members->xInvocation, UNO_QUERY );
         if ( xIndexContainer.is() )
             xIndexReplace.set( xIndexContainer, UNO_QUERY );
         else
-            xIndexReplace.set( me->members->wrappedObject, UNO_QUERY );
+            xIndexReplace.set( me->members->xInvocation, UNO_QUERY );
 
         if ( xIndexReplace.is() && nIndex < 0 )
             nIndex += xIndexReplace->getCount();
@@ -1032,11 +1033,11 @@ int lcl_setitem_slice( PyUNO *me, PyObject *pKey, PyObject *pValue )
     {
         PyThreadDetach antiguard;
 
-        xIndexContainer.set( me->members->wrappedObject, UNO_QUERY );
+        xIndexContainer.set( me->members->xInvocation, UNO_QUERY );
         if ( xIndexContainer.is() )
             xIndexReplace.set( xIndexContainer, UNO_QUERY );
         else
-            xIndexReplace.set( me->members->wrappedObject, UNO_QUERY );
+            xIndexReplace.set( me->members->xInvocation, UNO_QUERY );
 
         if ( xIndexReplace.is() )
             nLen = xIndexReplace->getCount();
@@ -1165,12 +1166,12 @@ int lcl_setitem_string( PyUNO *me, PyObject *pKey, PyObject *pValue )
     {
         PyThreadDetach antiguard;
 
-        Reference< XNameContainer > xNameContainer( me->members->wrappedObject, UNO_QUERY );
+        Reference< XNameContainer > xNameContainer( me->members->xInvocation, UNO_QUERY );
         Reference< XNameReplace > xNameReplace;
         if ( xNameContainer.is() )
             xNameReplace.set( xNameContainer, UNO_QUERY );
         else
-            xNameReplace.set( me->members->wrappedObject, UNO_QUERY );
+            xNameReplace.set( me->members->xInvocation, UNO_QUERY );
 
         if ( xNameReplace.is() )
         {
@@ -1277,17 +1278,17 @@ PyObject* PyUNO_iter( PyObject *self )
         {
             PyThreadDetach antiguard;
 
-            xEnumerationAccess.set( me->members->wrappedObject, UNO_QUERY );
+            xEnumerationAccess.set( me->members->xInvocation, UNO_QUERY );
             if ( xEnumerationAccess.is() )
                 xEnumeration = xEnumerationAccess->createEnumeration();
             else
                 xEnumeration.set( me->members->wrappedObject, UNO_QUERY );
 
             if ( !xEnumeration.is() )
-                xIndexAccess.set( me->members->wrappedObject, UNO_QUERY );
+                xIndexAccess.set( me->members->xInvocation, UNO_QUERY );
 
             if ( !xIndexAccess.is() )
-                xNameAccess.set( me->members->wrappedObject, UNO_QUERY );
+                xNameAccess.set( me->members->xInvocation, UNO_QUERY );
         }
 
         // XEnumerationAccess iterator
@@ -1373,7 +1374,7 @@ int PyUNO_contains( PyObject *self, PyObject *pKey )
             {
                 PyThreadDetach antiguard;
 
-                xNameAccess.set( me->members->wrappedObject, UNO_QUERY );
+                xNameAccess.set( me->members->xInvocation, UNO_QUERY );
                 if ( xNameAccess.is() )
                 {
                     bool hasKey = xNameAccess->hasByName( sKey );
@@ -1765,51 +1766,43 @@ PyRef getPyUnoClass()
     return PyRef( reinterpret_cast< PyObject * > ( &PyUNOType ) );
 }
 
-PyObject* PyUNO_new (
-    const Any & targetInterface, const Reference<XSingleServiceFactory> &ssf)
-{
-    Reference<XInterface> tmp_interface;
-
-    targetInterface >>= tmp_interface;
-
-    if (!tmp_interface.is ())
-    {
-        // empty reference !
-        Py_INCREF( Py_None );
-        return Py_None;
-    }
-   return PyUNO_new_UNCHECKED (targetInterface, ssf);
-}
-
-
-PyObject* PyUNO_new_UNCHECKED (
+PyRef PyUNO_new (
     const Any &targetInterface,
-    const Reference<XSingleServiceFactory> &ssf )
+    const Reference<XSingleServiceFactory> &ssf,
+    const bool bCheckExisting )
 {
-    Reference<XInterface> tmp_interface;
-    Reference<XInvocation2> tmp_invocation;
+    Reference<XInvocation2> xInvocation;
+
     {
         PyThreadDetach antiguard;
-        Sequence<Any> arguments(1);
-        arguments[0] <<= targetInterface;
-        tmp_interface = ssf->createInstanceWithArguments(arguments);
-        tmp_invocation.set(tmp_interface, UNO_QUERY);
-        if (!tmp_invocation.is() && tmp_interface.is()) {
+        xInvocation.set(
+            ssf->createInstanceWithArguments( Sequence<Any>( &targetInterface, 1 ) ), UNO_QUERY );
+        if( !xInvocation.is() )
             throw RuntimeException("XInvocation2 not implemented, cannot interact with object");
+
+        if (bCheckExisting)
+        {
+            Reference<XUnoTunnel> xUnoTunnel (
+                xInvocation->getIntrospection()->queryAdapter(cppu::UnoType<XUnoTunnel>::get()), UNO_QUERY );
+            if( xUnoTunnel.is() )
+            {
+                sal_Int64 that = xUnoTunnel->getSomething( ::pyuno::Adapter::getUnoTunnelImplementationId() );
+                if( that )
+                    return PyRef( reinterpret_cast<Adapter*>(that)->getWrappedObject() );
+            }
         }
     }
-    if (!tmp_interface.is())
-    {
-        Py_INCREF( Py_None );
-        return Py_None;
-    }
+    if( !Py_IsInitialized() )
+        throw RuntimeException();
+
     PyUNO* self = PyObject_New (PyUNO, &PyUNOType);
     if (self == NULL)
-        return NULL; // == error
+        return PyRef(); // == error
     self->members = new PyUNOInternals();
-    self->members->xInvocation = tmp_invocation;
+    self->members->xInvocation = xInvocation;
     self->members->wrappedObject = targetInterface;
-    return reinterpret_cast<PyObject*>(self);
+    return PyRef( reinterpret_cast<PyObject*>(self), SAL_NO_ACQUIRE );
+
 }
 
 }
diff --git a/pyuno/source/module/pyuno_adapter.cxx b/pyuno/source/module/pyuno_adapter.cxx
index 1fbfcba..ce4995d 100644
--- a/pyuno/source/module/pyuno_adapter.cxx
+++ b/pyuno/source/module/pyuno_adapter.cxx
@@ -80,6 +80,9 @@ sal_Int64 Adapter::getSomething( const Sequence< sal_Int8 > &id) throw (RuntimeE
 void raiseInvocationTargetExceptionWhenNeeded( const Runtime &runtime )
     throw ( InvocationTargetException )
 {
+    if( !Py_IsInitialized() )
+        throw InvocationTargetException();
+
     if( PyErr_Occurred() )
     {
         PyRef excType, excValue, excTraceback;
@@ -195,6 +198,9 @@ Any Adapter::invoke( const OUString &aFunctionName,
     {
     PyThreadAttach guard( mInterpreter );
     {
+        if( !Py_IsInitialized() )
+            throw InvocationTargetException();
+
         // convert parameters to python args
         // TODO: Out parameter
         Runtime runtime;
@@ -219,12 +225,18 @@ Any Adapter::invoke( const OUString &aFunctionName,
         for( i = 0; i < size ; i ++  )
         {
             PyRef val = runtime.any2PyObject( aParams[i] );
+
+            // any2PyObject() can release the GIL
+            if( !Py_IsInitialized() )
+                throw InvocationTargetException();
+
             PyTuple_SetItem( argsTuple.get(), i, val.getAcquired() );
         }
 
         // get callable
         PyRef method(PyObject_GetAttrString( mWrappedObject.get(), TO_ASCII(aFunctionName)),
                      SAL_NO_ACQUIRE);
+
         raiseInvocationTargetExceptionWhenNeeded( runtime);
         if( !method.is() )
         {
@@ -355,9 +367,16 @@ void Adapter::setValue( const OUString & aPropertyName, const Any & value )
     PyThreadAttach guard( mInterpreter );
     try
     {
+        if( !Py_IsInitialized() )
+            throw InvocationTargetException();
+
         Runtime runtime;
         PyRef obj = runtime.any2PyObject( value );
 
+        // any2PyObject() can release the GIL
+        if( !Py_IsInitialized() )
+            throw InvocationTargetException();
+
         PyObject_SetAttrString(
             mWrappedObject.get(), TO_ASCII(aPropertyName), obj.get() );
         raiseInvocationTargetExceptionWhenNeeded( runtime);
@@ -375,6 +394,10 @@ Any Adapter::getValue( const OUString & aPropertyName )
     Any ret;
     PyThreadAttach guard( mInterpreter );
     {
+        // Should probably be InvocationTargetException, but the interface doesn't allow it
+        if( !Py_IsInitialized() )
+            throw RuntimeException();
+
         Runtime runtime;
         PyRef pyRef(
             PyObject_GetAttrString( mWrappedObject.get(), TO_ASCII(aPropertyName) ),
@@ -404,6 +427,10 @@ sal_Bool Adapter::hasProperty( const OUString & aPropertyName )
     bool bRet = false;
     PyThreadAttach guard( mInterpreter );
     {
+        // Should probably be InvocationTargetException, but the interface doesn't allow it
+        if( !Py_IsInitialized() )
+            throw RuntimeException();
+
         bRet = PyObject_HasAttrString(
             mWrappedObject.get() , TO_ASCII( aPropertyName ));
     }
diff --git a/pyuno/source/module/pyuno_impl.hxx b/pyuno/source/module/pyuno_impl.hxx
index 11fbfa2..669386f 100644
--- a/pyuno/source/module/pyuno_impl.hxx
+++ b/pyuno/source/module/pyuno_impl.hxx
@@ -205,13 +205,10 @@ typedef std::unordered_set< PyRef , PyRef::Hash , std::equal_to<PyRef> > ClassSe
 
 int PyUNO_initType();
 
-PyObject* PyUNO_new(
+PyRef PyUNO_new (
     const com::sun::star::uno::Any & targetInterface,
-    const com::sun::star::uno::Reference<com::sun::star::lang::XSingleServiceFactory> & ssf);
-
-PyObject* PyUNO_new_UNCHECKED (
-    const com::sun::star::uno::Any & targetInterface,
-    const com::sun::star::uno::Reference<com::sun::star::lang::XSingleServiceFactory> & ssf);
+    const com::sun::star::uno::Reference<com::sun::star::lang::XSingleServiceFactory> & ssf,
+    const bool bCheckExisting );
 
 typedef struct
 {
diff --git a/pyuno/source/module/pyuno_module.cxx b/pyuno/source/module/pyuno_module.cxx
index 722e922..7d282c2 100644
--- a/pyuno/source/module/pyuno_module.cxx
+++ b/pyuno/source/module/pyuno_module.cxx
@@ -406,8 +406,8 @@ static PyObject *createUnoStructHelper(
                     if (idl_class.is ())
                     {
                         idl_class->createObject (IdlStruct);
-                        PyUNO *me = reinterpret_cast<PyUNO*>(PyUNO_new_UNCHECKED( IdlStruct, c->xInvocation ));
-                        PyRef returnCandidate( reinterpret_cast<PyObject*>(me), SAL_NO_ACQUIRE );
+                        PyRef returnCandidate( PyUNO_new( IdlStruct, c->xInvocation, false ) );
+                        PyUNO *me = reinterpret_cast<PyUNO*>( returnCandidate.get() );
                         TypeDescription desc( typeName );
                         OSL_ASSERT( desc.is() ); // could already instantiate an XInvocation2 !
 
diff --git a/pyuno/source/module/pyuno_runtime.cxx b/pyuno/source/module/pyuno_runtime.cxx
index cda8e8b..f14b84b 100644
--- a/pyuno/source/module/pyuno_runtime.cxx
+++ b/pyuno/source/module/pyuno_runtime.cxx
@@ -481,7 +481,7 @@ PyRef Runtime::any2PyObject (const Any &a ) const
     case typelib_TypeClass_STRUCT:
     {
         PyRef excClass = getClass( a.getValueType().getTypeName(), *this );
-        PyRef value = PyRef( PyUNO_new_UNCHECKED (a, getImpl()->cargo->xInvocation), SAL_NO_ACQUIRE);
+        PyRef value = PyUNO_new( a, getImpl()->cargo->xInvocation, false );
         PyRef argsTuple( PyTuple_New( 1 ) , SAL_NO_ACQUIRE, NOT_NULL );
         PyTuple_SetItem( argsTuple.get() , 0 , value.getAcquired() );
         PyRef ret( PyObject_CallObject( excClass.get() , argsTuple.get() ), SAL_NO_ACQUIRE );
@@ -551,22 +551,12 @@ PyRef Runtime::any2PyObject (const Any &a ) const
     }
     case typelib_TypeClass_INTERFACE:
     {
-        // fdo#46678 must unlock GIL because getSomething could acquire locks,
-        // and queryInterface too...
-        {
-            PyThreadDetach d;
+        Reference<XInterface> tmp_interface;
+        a >>= tmp_interface;
+        if (!tmp_interface.is ())
+            return Py_None;
 
-            Reference<XUnoTunnel> tunnel;
-            a >>= tunnel;
-            if (tunnel.is())
-            {
-                sal_Int64 that = tunnel->getSomething( ::pyuno::Adapter::getUnoTunnelImplementationId() );
-                if( that )
-                    return reinterpret_cast<Adapter*>(that)->getWrappedObject();
-            }
-        }
-        //This is just like the struct case:
-        return PyRef( PyUNO_new (a, getImpl()->cargo->xInvocation), SAL_NO_ACQUIRE );
+        return PyUNO_new (a, getImpl()->cargo->xInvocation, true);
     }
     default:
     {
diff --git a/stoc/source/inspect/introspection.cxx b/stoc/source/inspect/introspection.cxx
index cd621b8..98a18c0 100644
--- a/stoc/source/inspect/introspection.cxx
+++ b/stoc/source/inspect/introspection.cxx
@@ -44,6 +44,7 @@
 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
 #include <com/sun/star/lang/XServiceInfo.hpp>
 #include <com/sun/star/lang/XEventListener.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
 #include <com/sun/star/reflection/XIdlReflection.hpp>
 #include <com/sun/star/reflection/XIdlClass.hpp>
 #include <com/sun/star/reflection/XIdlField2.hpp>
@@ -86,7 +87,7 @@ namespace
 typedef WeakImplHelper< XIntrospectionAccess, XMaterialHolder, XExactName,
                         XPropertySet, XFastPropertySet, XPropertySetInfo,
                         XNameContainer, XIndexContainer, XEnumerationAccess,
-                        XIdlArray > IntrospectionAccessHelper;
+                        XIdlArray, XUnoTunnel > IntrospectionAccessHelper;
 
 
 
@@ -201,11 +202,14 @@ class IntrospectionAccessStatic_Impl: public salhelper::SimpleReferenceObject
     bool mbFastPropSet;
     bool mbElementAccess;
     bool mbNameAccess;
+    bool mbNameReplace;
     bool mbNameContainer;
     bool mbIndexAccess;
+    bool mbIndexReplace;
     bool mbIndexContainer;
     bool mbEnumerationAccess;
     bool mbIdlArray;
+    bool mbUnoTunnel;
 
     // Original handles of FastPropertySets
     sal_Int32* mpOrgPropertyHandleArray;
@@ -273,11 +277,14 @@ IntrospectionAccessStatic_Impl::IntrospectionAccessStatic_Impl( Reference< XIdlR
     mbFastPropSet = false;
     mbElementAccess = false;
     mbNameAccess = false;
+    mbNameReplace = false;
     mbNameContainer = false;
     mbIndexAccess = false;
+    mbIndexReplace = false;
     mbIndexContainer = false;
     mbEnumerationAccess = false;
     mbIdlArray = false;
+    mbUnoTunnel = false;
 
     mpOrgPropertyHandleArray = NULL;
 
@@ -716,19 +723,27 @@ class ImplIntrospectionAccess : public IntrospectionAccessHelper
     // Original interfaces of the objects
     Reference<XElementAccess>       mxObjElementAccess;
     Reference<XNameContainer>       mxObjNameContainer;
+    Reference<XNameReplace>         mxObjNameReplace;
     Reference<XNameAccess>          mxObjNameAccess;
-    Reference<XIndexAccess>         mxObjIndexAccess;
     Reference<XIndexContainer>      mxObjIndexContainer;
+    Reference<XIndexReplace>        mxObjIndexReplace;
+    Reference<XIndexAccess>         mxObjIndexAccess;
     Reference<XEnumerationAccess>   mxObjEnumerationAccess;
     Reference<XIdlArray>            mxObjIdlArray;
 
     Reference<XElementAccess>       getXElementAccess();
     Reference<XNameContainer>       getXNameContainer();
+    Reference<XNameReplace>         getXNameReplace();
     Reference<XNameAccess>          getXNameAccess();
     Reference<XIndexContainer>      getXIndexContainer();
+    Reference<XIndexReplace>        getXIndexReplace();
     Reference<XIndexAccess>         getXIndexAccess();
     Reference<XEnumerationAccess>   getXEnumerationAccess();
     Reference<XIdlArray>            getXIdlArray();
+    Reference<XUnoTunnel>           getXUnoTunnel();
+
+    void cacheXNameContainer();
+    void cacheXIndexContainer();
 
 public:
     ImplIntrospectionAccess( const Any& obj, rtl::Reference< IntrospectionAccessStatic_Impl > const & pStaticImpl_ );
@@ -804,11 +819,13 @@ public:
     virtual Sequence< OUString > SAL_CALL getElementNames() throw( RuntimeException, std::exception ) SAL_OVERRIDE;
     virtual sal_Bool SAL_CALL hasByName(const OUString& Name) throw( RuntimeException, std::exception ) SAL_OVERRIDE;
 
+    // Methods from XNameReplace
+    virtual void SAL_CALL replaceByName(const OUString& Name, const Any& Element)
+        throw( IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException, std::exception ) SAL_OVERRIDE;
+
     // Methods from XNameContainer
     virtual void SAL_CALL insertByName(const OUString& Name, const Any& Element)
         throw( IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException, std::exception ) SAL_OVERRIDE;
-    virtual void SAL_CALL replaceByName(const OUString& Name, const Any& Element)
-        throw( IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException, std::exception ) SAL_OVERRIDE;
     virtual void SAL_CALL removeByName(const OUString& Name)
         throw( NoSuchElementException, WrappedTargetException, RuntimeException, std::exception ) SAL_OVERRIDE;
 
@@ -817,11 +834,13 @@ public:
     virtual Any SAL_CALL getByIndex(sal_Int32 Index)
         throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException, std::exception ) SAL_OVERRIDE;
 
+    // Methods from XIndexReplace
+    virtual void SAL_CALL replaceByIndex(sal_Int32 Index, const Any& Element)
+        throw( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException, std::exception ) SAL_OVERRIDE;
+
     // Methods from XIndexContainer
     virtual void SAL_CALL insertByIndex(sal_Int32 Index, const Any& Element)
         throw( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException, std::exception ) SAL_OVERRIDE;
-    virtual void SAL_CALL replaceByIndex(sal_Int32 Index, const Any& Element)
-        throw( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException, std::exception ) SAL_OVERRIDE;
     virtual void SAL_CALL removeByIndex(sal_Int32 Index)
         throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException, std::exception ) SAL_OVERRIDE;
 
@@ -836,6 +855,10 @@ public:
         throw( IllegalArgumentException, ArrayIndexOutOfBoundsException, RuntimeException, std::exception ) SAL_OVERRIDE;
     virtual void SAL_CALL set(Any& array, sal_Int32 index, const Any& value)
         throw( IllegalArgumentException, ArrayIndexOutOfBoundsException, RuntimeException, std::exception ) SAL_OVERRIDE;
+
+    // Methods from XUnoTunnel
+    virtual sal_Int64 SAL_CALL getSomething( const Sequence< sal_Int8 >& aIdentifier )
+        throw (RuntimeException, std::exception) SAL_OVERRIDE;
 };
 
 ImplIntrospectionAccess::ImplIntrospectionAccess
@@ -871,62 +894,138 @@ Reference<XElementAccess> ImplIntrospectionAccess::getXElementAccess()
     return mxObjElementAccess;
 }
 
+void ImplIntrospectionAccess::cacheXNameContainer()
+{
+    Reference<XNameContainer> xNameContainer;
+    Reference<XNameReplace> xNameReplace;
+    Reference<XNameAccess> xNameAccess;
+    if (mpStaticImpl->mbNameContainer)
+    {
+        xNameContainer = Reference<XNameContainer>::query( mxIface );
+        xNameReplace = Reference<XNameReplace>::query( xNameContainer );
+        xNameAccess = Reference<XNameAccess>::query( xNameContainer );
+    }
+    else if (mpStaticImpl->mbNameReplace)
+    {
+        xNameReplace = Reference<XNameReplace>::query( mxIface );
+        xNameAccess = Reference<XNameAccess>::query( xNameReplace );
+    }
+    else if (mpStaticImpl->mbNameAccess)
+    {
+        xNameAccess = Reference<XNameAccess>::query( mxIface );
+    }
+
+    {
+        MutexGuard aGuard( m_aMutex );
+        if( !mxObjNameContainer.is() )
+            mxObjNameContainer = xNameContainer;
+        if( !mxObjNameReplace.is() )
+            mxObjNameReplace = xNameReplace;
+        if( !mxObjNameAccess.is() )
+            mxObjNameAccess = xNameAccess;
+    }
+}
+
 Reference<XNameContainer> ImplIntrospectionAccess::getXNameContainer()
 {
-    ResettableGuard< Mutex > aGuard( m_aMutex );
+    ClearableGuard< Mutex > aGuard( m_aMutex );
 
     if( !mxObjNameContainer.is() )
     {
         aGuard.clear();
-        Reference<XNameContainer> xNameContainer = Reference<XNameContainer>::query( mxIface );
-        aGuard.reset();
-        if( !mxObjNameContainer.is() )
-            mxObjNameContainer = xNameContainer;
+        cacheXNameContainer();
     }
     return mxObjNameContainer;
 }
 
+Reference<XNameReplace> ImplIntrospectionAccess::getXNameReplace()
+{
+    ClearableGuard< Mutex > aGuard( m_aMutex );
+
+    if( !mxObjNameReplace.is() )
+    {
+        aGuard.clear();
+        cacheXNameContainer();
+    }
+    return mxObjNameReplace;
+}
+
 Reference<XNameAccess> ImplIntrospectionAccess::getXNameAccess()
 {
-    ResettableGuard< Mutex > aGuard( m_aMutex );
+    ClearableGuard< Mutex > aGuard( m_aMutex );
 
     if( !mxObjNameAccess.is() )
     {
         aGuard.clear();
-        Reference<XNameAccess> xNameAccess = Reference<XNameAccess>::query( mxIface );
-        aGuard.reset();
-        if( !mxObjNameAccess.is() )
-            mxObjNameAccess = xNameAccess;
+        cacheXNameContainer();
     }
     return mxObjNameAccess;
 }
 
+void ImplIntrospectionAccess::cacheXIndexContainer()
+{
+    Reference<XIndexContainer> xIndexContainer;
+    Reference<XIndexReplace> xIndexReplace;
+    Reference<XIndexAccess> xIndexAccess;
+    if (mpStaticImpl->mbIndexContainer)
+    {
+        xIndexContainer = Reference<XIndexContainer>::query( mxIface );
+        xIndexReplace = Reference<XIndexReplace>::query( xIndexContainer );
+        xIndexAccess = Reference<XIndexAccess>::query( xIndexContainer );
+    }
+    else if (mpStaticImpl->mbIndexReplace)
+    {
+        xIndexReplace = Reference<XIndexReplace>::query( mxIface );
+        xIndexAccess = Reference<XIndexAccess>::query( xIndexReplace );
+    }
+    else if (mpStaticImpl->mbIndexAccess)
+    {
+        xIndexAccess = Reference<XIndexAccess>::query( mxIface );
+    }
+
+    {
+        MutexGuard aGuard( m_aMutex );
+        if( !mxObjIndexContainer.is() )
+            mxObjIndexContainer = xIndexContainer;
+        if( !mxObjIndexReplace.is() )
+            mxObjIndexReplace = xIndexReplace;
+        if( !mxObjIndexAccess.is() )
+            mxObjIndexAccess = xIndexAccess;
+    }
+}
+
 Reference<XIndexContainer> ImplIntrospectionAccess::getXIndexContainer()
 {
-    ResettableGuard< Mutex > aGuard( m_aMutex );
+    ClearableGuard< Mutex > aGuard( m_aMutex );
 
     if( !mxObjIndexContainer.is() )
     {
         aGuard.clear();
-        Reference<XIndexContainer> xIndexContainer = Reference<XIndexContainer>::query( mxIface );
-        aGuard.reset();
-        if( !mxObjIndexContainer.is() )
-            mxObjIndexContainer = xIndexContainer;
+        cacheXIndexContainer();
     }
     return mxObjIndexContainer;
 }
 
+Reference<XIndexReplace> ImplIntrospectionAccess::getXIndexReplace()
+{
+    ClearableGuard< Mutex > aGuard( m_aMutex );
+
+    if( !mxObjIndexReplace.is() )
+    {
+        aGuard.clear();
+        cacheXIndexContainer();
+    }
+    return mxObjIndexReplace;
+}
+
 Reference<XIndexAccess> ImplIntrospectionAccess::getXIndexAccess()
 {
-    ResettableGuard< Mutex > aGuard( m_aMutex );
+    ClearableGuard< Mutex > aGuard( m_aMutex );
 
     if( !mxObjIndexAccess.is() )
     {
         aGuard.clear();
-        Reference<XIndexAccess> xIndexAccess = Reference<XIndexAccess>::query( mxIface );
-        aGuard.reset();
-        if( !mxObjIndexAccess.is() )
-            mxObjIndexAccess = xIndexAccess;
+        cacheXIndexContainer();
     }
     return mxObjIndexAccess;
 }
@@ -961,6 +1060,10 @@ Reference<XIdlArray> ImplIntrospectionAccess::getXIdlArray()
     return mxObjIdlArray;
 }
 
+Reference<XUnoTunnel> ImplIntrospectionAccess::getXUnoTunnel()
+{
+    return Reference<XUnoTunnel>::query( mxIface );
+}
 
 // Methods from XInterface
 Any SAL_CALL ImplIntrospectionAccess::queryInterface( const Type& rType )
@@ -983,11 +1086,14 @@ Any SAL_CALL ImplIntrospectionAccess::queryInterface( const Type& rType )
         if(   ( mpStaticImpl->mbElementAccess && (aRet = ::cppu::queryInterface
                     ( rType, static_cast< XElementAccess* >( static_cast< XNameAccess* >( this ) ) ) ).hasValue() )
             || ( mpStaticImpl->mbNameAccess && (aRet = ::cppu::queryInterface( rType, static_cast< XNameAccess* >( this ) ) ).hasValue() )
+            || ( mpStaticImpl->mbNameReplace && (aRet = ::cppu::queryInterface( rType, static_cast< XNameReplace* >( this ) ) ).hasValue() )
             || ( mpStaticImpl->mbNameContainer && (aRet = ::cppu::queryInterface( rType, static_cast< XNameContainer* >( this ) ) ).hasValue() )
             || ( mpStaticImpl->mbIndexAccess && (aRet = ::cppu::queryInterface( rType, static_cast< XIndexAccess* >( this ) ) ).hasValue() )
+            || ( mpStaticImpl->mbIndexReplace && (aRet = ::cppu::queryInterface( rType, static_cast< XIndexReplace* >( this ) ) ).hasValue() )
             || ( mpStaticImpl->mbIndexContainer && (aRet = ::cppu::queryInterface( rType, static_cast< XIndexContainer* >( this ) ) ).hasValue() )
             || ( mpStaticImpl->mbEnumerationAccess && (aRet = ::cppu::queryInterface( rType, static_cast< XEnumerationAccess* >( this ) ) ).hasValue() )
             || ( mpStaticImpl->mbIdlArray && (aRet = ::cppu::queryInterface( rType, static_cast< XIdlArray* >( this ) ) ).hasValue() )
+            || ( mpStaticImpl->mbUnoTunnel && (aRet = ::cppu::queryInterface( rType, static_cast< XUnoTunnel* >( this ) ) ).hasValue() )
           )
         {
         }
@@ -1141,7 +1247,7 @@ void ImplIntrospectionAccess::insertByName(const OUString& Name, const Any& Elem
 void ImplIntrospectionAccess::replaceByName(const OUString& Name, const Any& Element)
     throw( IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException, std::exception )
 {
-    getXNameContainer()->replaceByName( Name, Element );
+    getXNameReplace()->replaceByName( Name, Element );
 }
 
 void ImplIntrospectionAccess::removeByName(const OUString& Name)
@@ -1173,7 +1279,7 @@ void ImplIntrospectionAccess::insertByIndex(sal_Int32 Index, const Any& Element)
 void ImplIntrospectionAccess::replaceByIndex(sal_Int32 Index, const Any& Element)
     throw( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException, std::exception )
 {
-    getXIndexContainer()->replaceByIndex( Index, Element );
+    getXIndexReplace()->replaceByIndex( Index, Element );
 }
 
 void ImplIntrospectionAccess::removeByIndex(sal_Int32 Index)
@@ -1214,6 +1320,12 @@ void ImplIntrospectionAccess::set(Any& array, sal_Int32 index, const Any& value)
     getXIdlArray()->set( array, index, value );
 }
 
+// Methods from XUnoTunnel
+sal_Int64 ImplIntrospectionAccess::getSomething( const Sequence< sal_Int8 >& aIdentifier )
+        throw (RuntimeException, std::exception)
+{
+    return getXUnoTunnel()->getSomething( aIdentifier );
+}
 
 
 //*** Implementation of ImplIntrospectionAccess ***
@@ -1433,11 +1545,14 @@ Reference<XInterface> SAL_CALL ImplIntrospectionAccess::queryAdapter( const Type
         || rType == cppu::UnoType<XPropertySetInfo>::get()
         || rType == cppu::UnoType<XElementAccess>::get()
         || rType == cppu::UnoType<XNameAccess>::get()
+        || rType == cppu::UnoType<XNameReplace>::get()
         || rType == cppu::UnoType<XNameContainer>::get()
         || rType == cppu::UnoType<XIndexAccess>::get()
+        || rType == cppu::UnoType<XIndexReplace>::get()
         || rType == cppu::UnoType<XIndexContainer>::get()
         || rType == cppu::UnoType<XEnumerationAccess>::get()
-        || rType == cppu::UnoType<XIdlArray>::get() )
+        || rType == cppu::UnoType<XIdlArray>::get()
+        || rType == cppu::UnoType<XUnoTunnel>::get() )
     {
         queryInterface( rType ) >>= xRet;
     }
@@ -1971,6 +2086,14 @@ css::uno::Reference<css::beans::XIntrospectionAccess> Implementation::inspect(
                         {
                             rMethodConcept_i |= NAMECONTAINER;
                             pAccess->mbNameContainer = true;
+                            pAccess->mbNameReplace = true;
+                            pAccess->mbNameAccess = true;
+                            pAccess->mbElementAccess = true;
+                        } else if ((className
+                                    == "com.sun.star.container.XNameReplace"))
+                        {
+                            rMethodConcept_i |= NAMECONTAINER;
+                            pAccess->mbNameReplace = true;
                             pAccess->mbNameAccess = true;
                             pAccess->mbElementAccess = true;
                         } else if ((className
@@ -1984,6 +2107,14 @@ css::uno::Reference<css::beans::XIntrospectionAccess> Implementation::inspect(
                         {
                             rMethodConcept_i |= INDEXCONTAINER;
                             pAccess->mbIndexContainer = true;
+                            pAccess->mbIndexReplace = true;
+                            pAccess->mbIndexAccess = true;
+                            pAccess->mbElementAccess = true;
+                        } else if ((className
+                                    == "com.sun.star.container.XIndexReplace"))
+                        {
+                            rMethodConcept_i |= INDEXCONTAINER;
+                            pAccess->mbIndexReplace = true;
                             pAccess->mbIndexAccess = true;
                             pAccess->mbElementAccess = true;
                         } else if ((className
@@ -2002,6 +2133,10 @@ css::uno::Reference<css::beans::XIntrospectionAccess> Implementation::inspect(
                                    == "com.sun.star.reflection.XIdlArray")
                         {
                             pAccess->mbIdlArray = true;
+                        } else if (className
+                                   == "com.sun.star.lang.XUnoTunnel")
+                        {
+                            pAccess->mbUnoTunnel = true;
                         }
 
                         // If the name is too short, it isn't anything
diff --git a/stoc/source/invocation/invocation.cxx b/stoc/source/invocation/invocation.cxx
index 7671471..751901f 100644
--- a/stoc/source/invocation/invocation.cxx
+++ b/stoc/source/invocation/invocation.cxx
@@ -150,14 +150,15 @@ public:
         throw( IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException, std::exception ) SAL_OVERRIDE
         { _xNameContainer->insertByName( Name, Element ); }
 
-    virtual void SAL_CALL replaceByName( const OUString& Name, const Any& Element )
-        throw( IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException, std::exception ) SAL_OVERRIDE
-        { _xNameContainer->replaceByName( Name, Element ); }
-
     virtual void SAL_CALL removeByName( const OUString& Name )
         throw( NoSuchElementException, WrappedTargetException, RuntimeException, std::exception ) SAL_OVERRIDE
         { _xNameContainer->removeByName( Name ); }
 
+    // XNameReplace
+    virtual void SAL_CALL replaceByName( const OUString& Name, const Any& Element )
+        throw( IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException, std::exception ) SAL_OVERRIDE
+        { _xNameReplace->replaceByName( Name, Element ); }
+
     // XNameAccess
     virtual Any SAL_CALL getByName( const OUString& Name )
         throw( NoSuchElementException, WrappedTargetException, RuntimeException, std::exception ) SAL_OVERRIDE
@@ -174,14 +175,15 @@ public:
         throw( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException, std::exception ) SAL_OVERRIDE
         { _xIndexContainer->insertByIndex( Index, Element ); }
 
-    virtual void SAL_CALL replaceByIndex( sal_Int32 Index, const Any& Element )
-        throw( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException, std::exception ) SAL_OVERRIDE
-        { _xIndexContainer->replaceByIndex( Index, Element ); }
-
     virtual void SAL_CALL removeByIndex( sal_Int32 Index )
         throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException, std::exception ) SAL_OVERRIDE
         { _xIndexContainer->removeByIndex( Index ); }
 
+    // XIndexReplace
+    virtual void SAL_CALL replaceByIndex( sal_Int32 Index, const Any& Element )
+        throw( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException, std::exception ) SAL_OVERRIDE
+        { _xIndexReplace->replaceByIndex( Index, Element ); }
+
     // XIndexAccess
     virtual sal_Int32 SAL_CALL getCount() throw( RuntimeException, std::exception ) SAL_OVERRIDE
         { return _xIndexAccess->getCount(); }
@@ -220,8 +222,10 @@ private:
 
     // supplied Interfaces
     Reference<XNameContainer>           _xNameContainer;
+    Reference<XNameReplace>             _xNameReplace;
     Reference<XNameAccess>              _xNameAccess;
     Reference<XIndexContainer>          _xIndexContainer;
+    Reference<XIndexReplace>            _xIndexReplace;
     Reference<XIndexAccess>             _xIndexAccess;
     Reference<XEnumerationAccess>       _xEnumerationAccess;
     Reference<XElementAccess>           _xElementAccess;
@@ -285,6 +289,11 @@ Any SAL_CALL Invocation_Impl::queryInterface( const Type & aType )
         if( _xNameContainer.is() )
             return makeAny( Reference< XNameContainer >( (static_cast< XNameContainer* >(this)) ) );
     }
+    else if ( aType == cppu::UnoType<XNameReplace>::get())
+    {
+        if( _xNameReplace.is() )
+            return makeAny( Reference< XNameReplace >( (static_cast< XNameReplace* >(this)) ) );
+    }
     else if ( aType == cppu::UnoType<XNameAccess>::get())
     {
         if( _xNameAccess.is() )
@@ -295,6 +304,11 @@ Any SAL_CALL Invocation_Impl::queryInterface( const Type & aType )
         if (_xIndexContainer.is())
             return makeAny( Reference< XIndexContainer >( (static_cast< XIndexContainer* >(this)) ) );
     }
+    else if ( aType == cppu::UnoType<XIndexReplace>::get())
+    {
+        if (_xIndexReplace.is())
+            return makeAny( Reference< XIndexReplace >( (static_cast< XIndexReplace* >(this)) ) );
+    }
     else if ( aType == cppu::UnoType<XIndexAccess>::get())
     {
         if (_xIndexAccess.is())
@@ -371,8 +385,10 @@ void Invocation_Impl::setMaterial( const Any& rMaterial )
         _xElementAccess     = Reference<XElementAccess>::query( _xDirect );
         _xEnumerationAccess = Reference<XEnumerationAccess>::query( _xDirect );
         _xIndexAccess       = Reference<XIndexAccess>::query( _xDirect );
+        _xIndexReplace      = Reference<XIndexReplace>::query( _xDirect );
         _xIndexContainer    = Reference<XIndexContainer>::query( _xDirect );
         _xNameAccess        = Reference<XNameAccess>::query( _xDirect );
+        _xNameReplace       = Reference<XNameReplace>::query( _xDirect );
         _xNameContainer     = Reference<XNameContainer>::query( _xDirect );
         _xENDirect          = Reference<XExactName>::query( _xDirect );
         _xDirect2           = Reference<XInvocation2>::query( _xDirect );
@@ -405,6 +421,10 @@ void Invocation_Impl::setMaterial( const Any& rMaterial )
 
                     if( _xIndexAccess.is() )
                     {
+                        _xIndexReplace = Reference<XIndexReplace>::query(
+                             _xIntrospectionAccess->queryAdapter(
+                                        cppu::UnoType<XIndexReplace>::get()) );
+
                         _xIndexContainer = Reference<XIndexContainer>::query(
                              _xIntrospectionAccess->queryAdapter(
                                         cppu::UnoType<XIndexContainer>::get()) );
@@ -416,6 +436,10 @@ void Invocation_Impl::setMaterial( const Any& rMaterial )
 
                     if( _xNameAccess.is() )
                     {
+                        _xNameReplace = Reference<XNameReplace>::query(
+                                   _xIntrospectionAccess->queryAdapter(
+                                       cppu::UnoType<XNameReplace>::get()) );
+
                         _xNameContainer = Reference<XNameContainer>::query(
                                    _xIntrospectionAccess->queryAdapter(
                                        cppu::UnoType<XNameContainer>::get()) );
@@ -559,6 +583,8 @@ void Invocation_Impl::setValue( const OUString& PropertyName, const Any& Value )
             // NameContainer
             else if( _xNameContainer.is() )
             {
+                // Note: This misfeature deliberately not adapted to apply to objects which
+                // have XNameReplace but not XNameContainer
                 Any aConv;
                 Reference < XIdlClass > r =
                     TypeToIdlClass( _xNameContainer->getElementType(), xCoreReflection );
@@ -1002,6 +1028,10 @@ Sequence< Type > SAL_CALL Invocation_Impl::getTypes() throw( RuntimeException, s
         {
             pTypes[ n++ ] = cppu::UnoType<XNameContainer>::get();
         }
+        if( _xNameReplace.is() )
+        {
+            pTypes[ n++ ] = cppu::UnoType<XNameReplace>::get();
+        }
         if( _xNameAccess.is() )
         {
             pTypes[ n++ ] = cppu::UnoType<XNameAccess>::get();
@@ -1010,6 +1040,10 @@ Sequence< Type > SAL_CALL Invocation_Impl::getTypes() throw( RuntimeException, s
         {
             pTypes[ n++ ] = cppu::UnoType<XIndexContainer>::get();
         }
+        if (_xIndexReplace.is())
+        {
+            pTypes[ n++ ] = cppu::UnoType<XIndexReplace>::get();
+        }
         if (_xIndexAccess.is())
         {
             pTypes[ n++ ] = cppu::UnoType<XIndexAccess>::get();


More information about the Libreoffice-commits mailing list