Kaydet (Commit) 98dc4bb8 authored tarafından Kohei Yoshida's avatar Kohei Yoshida

Extended UNO's script API to allow adding of multiple listeners at once.

üst acd31343
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
#include <com/sun/star/registry/XRegistryKey.hpp> #include <com/sun/star/registry/XRegistryKey.hpp>
#include <com/sun/star/beans/XIntrospection.hpp> #include <com/sun/star/beans/XIntrospection.hpp>
#include <com/sun/star/beans/MethodConcept.hpp> #include <com/sun/star/beans/MethodConcept.hpp>
#include <com/sun/star/script/XEventAttacher.hpp> #include <com/sun/star/script/XEventAttacher2.hpp>
#include <com/sun/star/script/XTypeConverter.hpp> #include <com/sun/star/script/XTypeConverter.hpp>
#include <com/sun/star/script/XAllListener.hpp> #include <com/sun/star/script/XAllListener.hpp>
#include <com/sun/star/script/XInvocationAdapterFactory.hpp> #include <com/sun/star/script/XInvocationAdapterFactory.hpp>
...@@ -214,7 +214,7 @@ sal_Bool SAL_CALL InvocationToAllListenerMapper::hasProperty(const OUString& Nam ...@@ -214,7 +214,7 @@ sal_Bool SAL_CALL InvocationToAllListenerMapper::hasProperty(const OUString& Nam
// class EventAttacherImpl // class EventAttacherImpl
// represents an implementation of the EventAttacher service // represents an implementation of the EventAttacher service
//************************************************************************* //*************************************************************************
class EventAttacherImpl : public WeakImplHelper3 < XEventAttacher, XInitialization, XServiceInfo > class EventAttacherImpl : public WeakImplHelper3 < XEventAttacher2, XInitialization, XServiceInfo >
{ {
public: public:
EventAttacherImpl( const Reference< XMultiServiceFactory >& ); EventAttacherImpl( const Reference< XMultiServiceFactory >& );
...@@ -246,10 +246,22 @@ public: ...@@ -246,10 +246,22 @@ public:
const Reference< XEventListener >& aToRemoveListener) const Reference< XEventListener >& aToRemoveListener)
throw( IllegalArgumentException, IntrospectionException, RuntimeException ); throw( IllegalArgumentException, IntrospectionException, RuntimeException );
// XEventAttacher2
virtual Sequence< Reference<XEventListener> > SAL_CALL attachMultipleEventListeners(
const Reference<XInterface>& xObject, const Sequence<com::sun::star::script::EventListener>& aListeners )
throw( IllegalArgumentException, ServiceNotRegisteredException, CannotCreateAdapterException, IntrospectionException, RuntimeException );
// used by FilterAllListener_Impl // used by FilterAllListener_Impl
Reference< XTypeConverter > getConverter() throw( Exception ); Reference< XTypeConverter > getConverter() throw( Exception );
friend class FilterAllListenerImpl; friend class FilterAllListenerImpl;
private:
Sequence< Reference<XEventListener> > attachListeners(
const Reference<XInterface>& xObject,
const Sequence< Reference<XAllListener> >& AllListeners,
const Sequence<com::sun::star::script::EventListener>& aListeners );
private: private:
Mutex m_aMutex; Mutex m_aMutex;
Reference< XMultiServiceFactory > m_xSMgr; Reference< XMultiServiceFactory > m_xSMgr;
...@@ -694,6 +706,152 @@ Reference< XEventListener > EventAttacherImpl::attachListener ...@@ -694,6 +706,152 @@ Reference< XEventListener > EventAttacherImpl::attachListener
return xRet; return xRet;
} }
Sequence< Reference<XEventListener> > EventAttacherImpl::attachListeners(
const Reference<XInterface>& xObject,
const Sequence< Reference<XAllListener> >& AllListeners,
const Sequence<com::sun::star::script::EventListener>& aListeners )
{
sal_Int32 nCount = aListeners.getLength();
if (nCount != AllListeners.getLength())
// This is a prerequisite!
throw RuntimeException();
if (!xObject.is())
throw IllegalArgumentException();
Reference< XInvocationAdapterFactory > xInvocationAdapterFactory = getInvocationAdapterService();
if( !xInvocationAdapterFactory.is() )
throw ServiceNotRegisteredException();
Reference< XIdlReflection > xReflection = getReflection();
if( !xReflection.is() )
throw ServiceNotRegisteredException();
// Sign in, Call the fitting addListener method
// First Introspection, as the Methods can be analyzed in the same way
// For better perfomance it is implemented here again or make the Impl-Method
// of the Introspection configurable for this purpose.
Reference< XIntrospection > xIntrospection = getIntrospection();
if( !xIntrospection.is() )
return Sequence< Reference<XEventListener> >();
// Inspect Introspection
Any aObjAny( &xObject, ::getCppuType(static_cast<const Reference<XInterface>*>(0)) );
Reference<XIntrospectionAccess> xAccess = xIntrospection->inspect(aObjAny);
if (!xAccess.is())
return Sequence< Reference<XEventListener> >();
Sequence< Reference<XEventListener> > aRet(nCount);
for (sal_Int32 i = 0; i < nCount; ++i)
{
Reference<XEventListener> xRet = NULL;
const Reference<XAllListener>& AllListener = aListeners[i].AllListener;
const Any& Helper = aListeners[i].Helper;
const OUString& ListenerType = aListeners[i].ListenerType;
const OUString& AddListenerParam = aListeners[i].AddListenerParam;
// Construct the name of the addListener-Method.
OUString aAddListenerName;
OUString aListenerName( ListenerType );
sal_Int32 nIndex = aListenerName.lastIndexOf( '.' );
// set index to the interface name without package name
if( nIndex == -1 )
// not found
nIndex = 0;
else
nIndex++;
if( aListenerName[nIndex] == 'X' )
// erase X from the interface name
aListenerName = aListenerName.copy( nIndex +1 );
aAddListenerName = OUString( RTL_CONSTASCII_USTRINGPARAM( "add" ) ) + aListenerName;
// Send Methods to the correct addListener-Method
Sequence< Reference< XIdlMethod > > aMethodSeq = xAccess->getMethods( MethodConcept::LISTENER );
sal_uInt32 j, nLen = aMethodSeq.getLength();
const Reference< XIdlMethod >* pMethods = aMethodSeq.getConstArray();
for( j = 0 ; j < nLen ; j++ )
{
const Reference< XIdlMethod >& rxMethod = pMethods[j];
// Is it the correct method?
OUString aMethName = rxMethod->getName();
if( aAddListenerName == aMethName )
{
Sequence< Reference< XIdlClass > > params = rxMethod->getParameterTypes();
sal_uInt32 nParamCount = params.getLength();
Reference< XIdlClass > xListenerType;
if( nParamCount == 1 )
xListenerType = params.getConstArray()[0];
else if( nParamCount == 2 )
xListenerType = params.getConstArray()[1];
// Request Adapter for the actual Listener type
Reference< XInterface > xAdapter = createAllListenerAdapter
( xInvocationAdapterFactory, xListenerType, AllListener, Helper );
if( !xAdapter.is() )
throw CannotCreateAdapterException();
xRet = Reference< XEventListener >( xAdapter, UNO_QUERY );
// Just the Listener as parameter?
if( nParamCount == 1 )
{
Sequence< Any > args( 1 );
args.getArray()[0] <<= xAdapter;
try
{
rxMethod->invoke( aObjAny, args );
}
catch( InvocationTargetException& )
{
throw IntrospectionException();
}
}
// Else, pass the other parameter now
else if( nParamCount == 2 )
{
Sequence< Any > args( 2 );
Any* pAnys = args.getArray();
// Check the type of the 1st parameter
Reference< XIdlClass > xParamClass = params.getConstArray()[0];
if( xParamClass->getTypeClass() == TypeClass_STRING )
{
pAnys[0] <<= AddListenerParam;
}
// 2nd Parameter == Listener? TODO: Test!
pAnys[1] <<= xAdapter;
// TODO: Convert String -> ?
// else
try
{
rxMethod->invoke( aObjAny, args );
}
catch( InvocationTargetException& )
{
throw IntrospectionException();
}
}
break;
// else...
// Anything else is not supported
}
}
aRet[nCount] = xRet;
}
return aRet;
}
// XEventAttacher // XEventAttacher
Reference< XEventListener > EventAttacherImpl::attachSingleEventListener Reference< XEventListener > EventAttacherImpl::attachSingleEventListener
( (
...@@ -817,6 +975,21 @@ void EventAttacherImpl::removeListener ...@@ -817,6 +975,21 @@ void EventAttacherImpl::removeListener
} }
} }
Sequence< Reference<XEventListener> > EventAttacherImpl::attachMultipleEventListeners(
const Reference<XInterface>& xObject, const Sequence<com::sun::star::script::EventListener>& aListeners )
throw( IllegalArgumentException, ServiceNotRegisteredException, CannotCreateAdapterException, IntrospectionException, RuntimeException )
{
sal_Int32 nCount = aListeners.getLength();
Sequence< Reference<XAllListener> > aFilterListeners(nCount);
for (sal_Int32 i = 0; i < nCount; ++i)
{
aFilterListeners[i] = (XAllListener*)
new FilterAllListenerImpl(this, aListeners[i].EventMethod, aListeners[i].AllListener);
}
return attachListeners(xObject, aFilterListeners, aListeners);
}
} }
extern "C" extern "C"
......
...@@ -150,6 +150,48 @@ using ::rtl::OUStringBuffer; ...@@ -150,6 +150,48 @@ using ::rtl::OUStringBuffer;
using ::boost::shared_ptr; using ::boost::shared_ptr;
using ::std::vector; using ::std::vector;
#include <stdio.h>
#include <string>
#include <sys/time.h>
namespace {
class StackPrinter
{
public:
explicit StackPrinter(const char* msg) :
msMsg(msg)
{
fprintf(stdout, "%s: --begin\n", msMsg.c_str());
mfStartTime = getTime();
}
~StackPrinter()
{
double fEndTime = getTime();
fprintf(stdout, "%s: --end (duration: %g sec)\n", msMsg.c_str(), (fEndTime-mfStartTime));
}
void printTime(int line) const
{
double fEndTime = getTime();
fprintf(stdout, "%s: --(%d) (duration: %g sec)\n", msMsg.c_str(), line, (fEndTime-mfStartTime));
}
private:
double getTime() const
{
timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec + tv.tv_usec / 1000000.0;
}
::std::string msMsg;
double mfStartTime;
};
}
// STATIC DATA ----------------------------------------------------------- // STATIC DATA -----------------------------------------------------------
// Stream-Namen im Storage // Stream-Namen im Storage
...@@ -1014,6 +1056,7 @@ static void lcl_parseHtmlFilterOption(const OUString& rOption, LanguageType& rLa ...@@ -1014,6 +1056,7 @@ static void lcl_parseHtmlFilterOption(const OUString& rOption, LanguageType& rLa
sal_Bool ScDocShell::ConvertFrom( SfxMedium& rMedium ) sal_Bool ScDocShell::ConvertFrom( SfxMedium& rMedium )
{ {
StackPrinter __stack_printer__("ScDocShell::ConvertFrom");
RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "sc", "nn93723", "ScDocShell::ConvertFrom" ); RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "sc", "nn93723", "ScDocShell::ConvertFrom" );
LoadMediumGuard aLoadGuard(&aDocument); LoadMediumGuard aLoadGuard(&aDocument);
......
...@@ -380,6 +380,7 @@ $(eval $(call gb_UnoApiTarget_add_idlfiles,udkapi,\ ...@@ -380,6 +380,7 @@ $(eval $(call gb_UnoApiTarget_add_idlfiles,udkapi,\
udkapi/com/sun/star/script/CannotConvertException \ udkapi/com/sun/star/script/CannotConvertException \
udkapi/com/sun/star/script/CannotCreateAdapterException \ udkapi/com/sun/star/script/CannotCreateAdapterException \
udkapi/com/sun/star/script/ContextInformation \ udkapi/com/sun/star/script/ContextInformation \
udkapi/com/sun/star/script/EventListener \
udkapi/com/sun/star/script/FailReason \ udkapi/com/sun/star/script/FailReason \
udkapi/com/sun/star/script/FinishEngineEvent \ udkapi/com/sun/star/script/FinishEngineEvent \
udkapi/com/sun/star/script/FinishReason \ udkapi/com/sun/star/script/FinishReason \
...@@ -400,6 +401,7 @@ $(eval $(call gb_UnoApiTarget_add_idlfiles,udkapi,\ ...@@ -400,6 +401,7 @@ $(eval $(call gb_UnoApiTarget_add_idlfiles,udkapi,\
udkapi/com/sun/star/script/XEngineListener \ udkapi/com/sun/star/script/XEngineListener \
udkapi/com/sun/star/script/XErrorQuery \ udkapi/com/sun/star/script/XErrorQuery \
udkapi/com/sun/star/script/XEventAttacher \ udkapi/com/sun/star/script/XEventAttacher \
udkapi/com/sun/star/script/XEventAttacher2 \
udkapi/com/sun/star/script/XEventAttacherManager \ udkapi/com/sun/star/script/XEventAttacherManager \
udkapi/com/sun/star/script/XInvocation \ udkapi/com/sun/star/script/XInvocation \
udkapi/com/sun/star/script/XInvocation2 \ udkapi/com/sun/star/script/XInvocation2 \
......
#ifndef __com_sun_star_script_EventListener_idl__
#define __com_sun_star_script_EventListener_idl__
#include <com/sun/star/script/XAllListener.idl>
module com { module sun { module star { module script {
struct EventListener
{
com::sun::star::script::XAllListener AllListener;
any Helper;
string ListenerType;
string AddListenerParam;
string EventMethod;
};
}; }; }; };
#endif
#ifndef __com_sun_star_script_XEventAttacher2_idl__
#define __com_sun_star_script_XEventAttacher2_idl__
#include <com/sun/star/script/XEventAttacher.idl>
#include <com/sun/star/lang/XEventListener.idl>
#include <com/sun/star/script/EventListener.idl>
module com { module sun { module star { module script {
interface XEventAttacher2: com::sun::star::script::XEventAttacher
{
sequence<com::sun::star::lang::XEventListener>
attachMultipleEventListeners(
[in] com::sun::star::uno::XInterface xTarget,
[in] sequence<com::sun::star::script::EventListener> aListeners )
raises( com::sun::star::lang::IllegalArgumentException,
com::sun::star::beans::IntrospectionException,
com::sun::star::script::CannotCreateAdapterException,
com::sun::star::lang::ServiceNotRegisteredException );
};
}; }; }; };
#endif
...@@ -46,6 +46,7 @@ IDLFILES=\ ...@@ -46,6 +46,7 @@ IDLFILES=\
ContextInformation.idl\ ContextInformation.idl\
Converter.idl\ Converter.idl\
Engine.idl\ Engine.idl\
EventListener.idl\
FailReason.idl\ FailReason.idl\
FinishEngineEvent.idl\ FinishEngineEvent.idl\
FinishReason.idl\ FinishReason.idl\
...@@ -64,6 +65,7 @@ IDLFILES=\ ...@@ -64,6 +65,7 @@ IDLFILES=\
XEngine.idl\ XEngine.idl\
XEngineListener.idl\ XEngineListener.idl\
XEventAttacher.idl\ XEventAttacher.idl\
XEventAttacher2.idl\
XEventAttacherManager.idl\ XEventAttacherManager.idl\
XInvocationAdapterFactory.idl\ XInvocationAdapterFactory.idl\
XInvocationAdapterFactory2.idl\ XInvocationAdapterFactory2.idl\
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment