1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: context.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_bridges.hxx"
39 #include <osl/diagnose.h>
40 #include <osl/interlck.h>
41 #include <osl/mutex.hxx>
43 #include "rtl/ustring.hxx"
45 #include <bridges/remote/context.h>
46 #include <bridges/remote/remote.h>
47 #include <bridges/remote/connection.h>
48 #include <bridges/remote/counter.hxx>
50 using namespace ::std
;
51 using namespace ::osl
;
52 using namespace ::rtl
;
56 extern "C" typedef void * (SAL_CALL
* MemAlloc
)(sal_Size
);
60 namespace remote_context
63 class remote_ContextImpl
:
67 remote_ContextImpl( remote_Connection
*pConnection
,
69 rtl_uString
*pDescription
,
70 rtl_uString
*pProtocol
,
71 remote_InstanceProvider
*pProvider
);
72 ~remote_ContextImpl();
74 static void SAL_CALL
thisAcquire( uno_Context
* );
75 static void SAL_CALL
thisRelease( uno_Context
* );
76 static void * SAL_CALL
thisQuery( uno_Context
* , rtl_uString
* );
77 static void SAL_CALL
thisAddDisposingListener( remote_Context
* , remote_DisposingListener
* );
78 static void SAL_CALL
thisRemoveDisposingListener( remote_Context
*, remote_DisposingListener
*);
79 static void SAL_CALL
thisDispose( remote_Context
*);
81 oslInterlockedCount m_nRef
;
83 list
< remote_DisposingListener
* > m_lstListener
;
90 struct equalOUString_Impl
92 sal_Bool
operator()(const OUString
& s1
, const OUString
& s2
) const
96 struct hashOUString_Impl
98 size_t operator()(const OUString
& rName
) const
99 { return rName
.hashCode(); }
111 #if OSL_DEBUG_LEVEL > 1
112 static MyCounter
thisCounter( "DEBUG : Context" );
117 ContextAdmin
*g_pTheContext
= 0;
124 static ContextAdmin
*getInstance();
126 // listener administration
127 void addContextListener( remote_contextListenerFunc listener
, void *pObject
);
128 void removeContextListener( remote_contextListenerFunc listener
, void *pObject
);
130 void fire( sal_Int32 nRemoteContextMode
,
132 rtl_uString
*sDescription
);
134 // context administration
135 uno_Context
*createAndRegisterContext(
136 remote_Connection
*pConnection
,
138 rtl_uString
*pDescription
,
139 rtl_uString
*pProtocol
,
140 remote_InstanceProvider
*pInstanceProvider
);
142 void revokeContext( uno_Context
*pRemoteContext
);
144 uno_Context
*get( rtl_uString
*pHost
);
146 rtl_uString
** getConnectionList(
147 sal_Int32
*pnStringCount
, MemAlloc memAlloc
);
150 ::osl::Mutex m_mutex
;
152 ContextMap m_mapContext
;
154 typedef std::list
< std::pair
< remote_contextListenerFunc
, void * > > List
;
158 ContextAdmin
*ContextAdmin::getInstance()
160 if( ! g_pTheContext
) {
161 ::osl::MutexGuard
guard( ::osl::Mutex::getGlobalMutex() );
162 if( ! g_pTheContext
) {
163 //TODO This memory is leaked; see #i63473# for when this should be
165 g_pTheContext
= new ContextAdmin
;
168 return g_pTheContext
;
171 void ContextAdmin::addContextListener( remote_contextListenerFunc listener
, void *pObject
)
173 ::osl::MutexGuard
guard( m_mutex
);
175 m_lstListener
.push_back( std::make_pair( listener
, pObject
) );
178 void ContextAdmin::removeContextListener( remote_contextListenerFunc listener
, void *pObject
)
180 ::osl::MutexGuard
guard( m_mutex
);
182 for (List::iterator
ii(m_lstListener
.begin()); ii
!= m_lstListener
.end();
185 if (ii
->first
== listener
&& ii
->second
== pObject
) {
186 m_lstListener
.erase( ii
);
192 void ContextAdmin::fire(
193 sal_Int32 nRemoteContextMode
,
195 rtl_uString
*sDescription
)
199 ::osl::MutexGuard
guard( m_mutex
);
202 for (List::iterator
i(lst
.begin()); i
!= lst
.end(); ++i
) {
203 (i
->first
)(i
->second
, nRemoteContextMode
, pName
, sDescription
);
207 uno_Context
*ContextAdmin::createAndRegisterContext( remote_Connection
*pConnection
,
209 rtl_uString
*pDescription
,
210 rtl_uString
*pProtocol
,
211 remote_InstanceProvider
*pInstanceProvider
)
213 ::osl::MutexGuard
guard( m_mutex
);
215 uno_Context
*pContext
= get( pIdStr
);
218 pContext
->release( pContext
);
222 remote_ContextImpl
*p
= new remote_ContextImpl( pConnection
,
228 p
->aBase
.acquire( (uno_Context
*) p
);
230 m_mapContext
[ OUString( pIdStr
) ] = (void*) p
;
232 fire( REMOTE_CONTEXT_CREATE
, pIdStr
, pDescription
);
233 return ( uno_Context
* )p
;
237 void ContextAdmin::revokeContext( uno_Context
*pRemoteContext
)
239 ::osl::MutexGuard
guard( m_mutex
);
241 remote_ContextImpl
*p
= ( remote_ContextImpl
* ) pRemoteContext
;
243 ContextMap::iterator ii
= m_mapContext
.find( p
->m_pName
);
244 OSL_ASSERT( ii
!= m_mapContext
.end() );
245 m_mapContext
.erase( ii
);
247 fire( REMOTE_CONTEXT_DESTROY
, p
->m_pName
, p
->m_pDescription
);
251 uno_Context
*ContextAdmin::get( rtl_uString
*pHost
)
253 ::osl::MutexGuard
guard( m_mutex
);
255 ContextMap::iterator ii
= m_mapContext
.find( OUString( (rtl_uString
*)pHost
) );
256 if( ii
== m_mapContext
.end() )
261 uno_Context
*p
= ( uno_Context
* ) (*ii
).second
;
267 rtl_uString
** ContextAdmin::getConnectionList(
268 sal_Int32
*pnStringCount
, MemAlloc memAlloc
)
270 ::osl::MutexGuard
guard( m_mutex
);
272 *pnStringCount
= m_mapContext
.size();
273 rtl_uString
**ppReturn
= ( rtl_uString
** )
274 memAlloc( sizeof( rtl_uString
* ) * m_mapContext
.size() );
275 memset( ppReturn
, 0 , sizeof( rtl_uString
* ) * m_mapContext
.size() );
278 for( ContextMap::iterator ii
= m_mapContext
.begin() ;
279 ii
!= m_mapContext
.end();
282 rtl_uString_assign( &( ppReturn
[i
] ), (*ii
).first
.pData
);
290 /*****************************
291 * remote_ContextImpl implementation
292 ****************************/
296 remote_ContextImpl::remote_ContextImpl( remote_Connection
*pConnection
,
298 rtl_uString
*pDescription
,
299 rtl_uString
*pProtocol
,
300 remote_InstanceProvider
*pProvider
) :
302 m_bDisposed( sal_False
)
304 m_pConnection
= pConnection
;
305 m_pConnection
->acquire( m_pConnection
);
307 m_pInstanceProvider
= pProvider
;
308 if( m_pInstanceProvider
)
310 m_pInstanceProvider
->acquire( pProvider
);
314 rtl_uString_acquire( m_pName
);
316 m_pDescription
= pDescription
;
317 rtl_uString_acquire( m_pDescription
);
319 m_pProtocol
= pProtocol
;
320 rtl_uString_acquire( pProtocol
);
322 aBase
.acquire
= thisAcquire
;
323 aBase
.release
= thisRelease
;
324 addDisposingListener
= thisAddDisposingListener
;
325 removeDisposingListener
= thisRemoveDisposingListener
;
326 dispose
= thisDispose
;
327 #if OSL_DEBUG_LEVEL > 1
328 thisCounter
.acquire();
332 remote_ContextImpl::~remote_ContextImpl()
334 // disposed must have been called
335 OSL_ASSERT( m_bDisposed
);
337 rtl_uString_release( m_pName
);
338 rtl_uString_release( m_pDescription
);
339 rtl_uString_release( m_pProtocol
);
340 #if OSL_DEBUG_LEVEL > 1
341 thisCounter
.release();
347 void remote_ContextImpl::thisAddDisposingListener( remote_Context
*pRemoteC
,
348 remote_DisposingListener
*pListener
)
350 remote_ContextImpl
*pImpl
= (remote_ContextImpl
* ) pRemoteC
;
352 ::osl::MutexGuard
guard( pImpl
->m_mutex
);
354 pListener
->acquire( pListener
);
355 pImpl
->m_lstListener
.push_back( pListener
);
358 void remote_ContextImpl::thisRemoveDisposingListener( remote_Context
*pRemoteC
,
359 remote_DisposingListener
*pListener
)
361 remote_ContextImpl
*pImpl
= (remote_ContextImpl
* ) pRemoteC
;
362 MutexGuard
guard( pImpl
->m_mutex
);
364 for( list
< remote_DisposingListener
* >::iterator ii
= pImpl
->m_lstListener
.begin() ;
365 ii
!= pImpl
->m_lstListener
.end();
368 if( (*ii
) == pListener
)
370 pImpl
->m_lstListener
.erase( ii
);
371 pListener
->release( pListener
);
377 void remote_ContextImpl::thisDispose( remote_Context
*pRemoteC
)
379 remote_ContextImpl
*pImpl
= ( remote_ContextImpl
* )pRemoteC
;
381 MutexGuard
guard( pImpl
->m_mutex
);
382 if( ! pImpl
->m_bDisposed
)
384 pImpl
->m_bDisposed
= sal_True
;
385 ContextAdmin::getInstance()->revokeContext( (uno_Context
* ) pRemoteC
);
387 if( pImpl
->m_pInstanceProvider
)
389 pImpl
->m_pInstanceProvider
->release( pImpl
->m_pInstanceProvider
);
390 pImpl
->m_pInstanceProvider
= 0;
393 pImpl
->m_pConnection
->release( pImpl
->m_pConnection
);
394 pImpl
->m_pConnection
= 0;
396 list
< remote_DisposingListener
* > lst
= pImpl
->m_lstListener
;
397 pImpl
->m_lstListener
.clear();
399 for( list
< remote_DisposingListener
* >::iterator ii
= lst
.begin();
403 (*ii
)->disposing( (*ii
) , pImpl
->m_pName
);
404 (*ii
)->release( (*ii
) );
412 void remote_ContextImpl::thisAcquire( uno_Context
*pRemoteC
)
414 remote_ContextImpl
*p
= SAL_REINTERPRET_CAST(remote_ContextImpl
* ,pRemoteC
);
415 osl_incrementInterlockedCount( &(p
->m_nRef
) );
418 void remote_ContextImpl::thisRelease( uno_Context
*pRemoteC
)
420 remote_ContextImpl
*p
= SAL_REINTERPRET_CAST( remote_ContextImpl
* , pRemoteC
);
421 if (! osl_decrementInterlockedCount( &(p
->m_nRef
) ))
423 // enshure, that this piece of code is not reentered
424 osl_incrementInterlockedCount( &(p
->m_nRef
) );
426 // dispose, if necessary
429 // restore the counter
430 osl_decrementInterlockedCount( &(p
->m_nRef
) );
438 // reanimated, but disposed !
443 void *remote_ContextImpl::thisQuery( uno_Context
* , rtl_uString
* )
449 } // end namespace remote_context
452 using namespace remote_context
;
454 //-----------------------
458 //-----------------------
459 extern "C" remote_Context
* SAL_CALL
460 remote_getContext( rtl_uString
*pIdString
)
462 return (remote_Context
*) ContextAdmin::getInstance()->get( pIdString
);
467 extern "C" remote_Context
* SAL_CALL
468 remote_createContext( remote_Connection
*pConnection
,
470 rtl_uString
*pDescription
,
471 rtl_uString
*pProtocol
,
472 remote_InstanceProvider
*pProvider
)
474 remote_ContextImpl
*p
= (remote_ContextImpl
* )
475 ContextAdmin::getInstance()->createAndRegisterContext(
482 return (remote_Context
* )p
;
486 extern "C" void SAL_CALL
487 remote_addContextListener( remote_contextListenerFunc listener
, void *pObject
)
489 ContextAdmin::getInstance()->addContextListener( listener
, pObject
);
492 extern "C" void SAL_CALL
493 remote_removeContextListener( remote_contextListenerFunc listener
, void *pObject
)
495 ContextAdmin::getInstance()->removeContextListener( listener
, pObject
);
498 extern "C" rtl_uString
** SAL_CALL
499 remote_getContextList( sal_Int32
*pnStringCount
, MemAlloc memAlloc
)
501 return ContextAdmin::getInstance()->getConnectionList( pnStringCount
, memAlloc
);