merge the formfield patch from ooo-build
[ooovba.git] / bridges / source / remote / context / context.cxx
blob6de2af9b9abc5368e8ef028dabc4bb24cd8c1c1d
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: context.cxx,v $
10 * $Revision: 1.12 $
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"
33 #include <stdio.h>
34 #include <string.h>
35 #include <list>
36 #include <hash_map>
37 #include <utility>
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;
54 namespace {
56 extern "C" typedef void * (SAL_CALL * MemAlloc)(sal_Size);
60 namespace remote_context
63 class remote_ContextImpl :
64 public remote_Context
66 public:
67 remote_ContextImpl( remote_Connection *pConnection,
68 rtl_uString *pIdStr,
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 *);
80 public:
81 oslInterlockedCount m_nRef;
82 sal_Bool m_bDisposed;
83 list < remote_DisposingListener * > m_lstListener;
84 Mutex m_mutex;
90 struct equalOUString_Impl
92 sal_Bool operator()(const OUString & s1, const OUString & s2) const
93 { return s1 == s2; }
96 struct hashOUString_Impl
98 size_t operator()(const OUString & rName) const
99 { return rName.hashCode(); }
102 typedef hash_map
104 OUString,
105 void *,
106 hashOUString_Impl,
107 equalOUString_Impl
109 ContextMap;
111 #if OSL_DEBUG_LEVEL > 1
112 static MyCounter thisCounter( "DEBUG : Context" );
113 #endif
115 class ContextAdmin;
117 ContextAdmin *g_pTheContext = 0;
121 class ContextAdmin
123 public:
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,
131 rtl_uString *sName,
132 rtl_uString *sDescription );
134 // context administration
135 uno_Context *createAndRegisterContext(
136 remote_Connection *pConnection,
137 rtl_uString *pIdStr,
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 );
149 private:
150 ::osl::Mutex m_mutex;
152 ContextMap m_mapContext;
154 typedef std::list< std::pair< remote_contextListenerFunc, void * > > List;
155 List m_lstListener;
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
164 // changed again:
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();
183 ++ii)
185 if (ii->first == listener && ii->second == pObject) {
186 m_lstListener.erase( ii );
187 break;
192 void ContextAdmin::fire(
193 sal_Int32 nRemoteContextMode,
194 rtl_uString *pName,
195 rtl_uString *sDescription )
197 List lst;
199 ::osl::MutexGuard guard( m_mutex );
200 lst = m_lstListener;
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,
208 rtl_uString *pIdStr,
209 rtl_uString *pDescription,
210 rtl_uString *pProtocol,
211 remote_InstanceProvider *pInstanceProvider )
213 ::osl::MutexGuard guard( m_mutex );
215 uno_Context *pContext = get( pIdStr );
216 if( pContext )
218 pContext->release( pContext );
219 return 0;
222 remote_ContextImpl *p = new remote_ContextImpl( pConnection,
223 pIdStr,
224 pDescription,
225 pProtocol,
226 pInstanceProvider );
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() )
258 return 0;
261 uno_Context *p = ( uno_Context * ) (*ii).second;
262 p->acquire( p );
263 return p;
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() );
277 sal_Int32 i = 0;
278 for( ContextMap::iterator ii = m_mapContext.begin() ;
279 ii != m_mapContext.end();
280 ++ii, i++ )
282 rtl_uString_assign( &( ppReturn[i] ), (*ii).first.pData );
285 return ppReturn;
290 /*****************************
291 * remote_ContextImpl implementation
292 ****************************/
296 remote_ContextImpl::remote_ContextImpl( remote_Connection *pConnection ,
297 rtl_uString *pIdStr,
298 rtl_uString *pDescription,
299 rtl_uString *pProtocol,
300 remote_InstanceProvider *pProvider ) :
301 m_nRef( 0 ),
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 );
313 m_pName = pIdStr;
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();
329 #endif
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();
342 #endif
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();
366 ++ii )
368 if( (*ii) == pListener )
370 pImpl->m_lstListener.erase( ii );
371 pListener->release( pListener );
372 break;
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();
400 ii != lst.end();
401 ++ii )
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
427 p->dispose( p );
429 // restore the counter
430 osl_decrementInterlockedCount( &(p->m_nRef) );
432 if( 0 == p->m_nRef )
434 delete p;
436 else
438 // reanimated, but disposed !
443 void *remote_ContextImpl::thisQuery( uno_Context * , rtl_uString * )
445 return 0;
449 } // end namespace remote_context
452 using namespace remote_context;
454 //-----------------------
456 // C-Interface
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,
469 rtl_uString *pIdStr,
470 rtl_uString *pDescription,
471 rtl_uString *pProtocol,
472 remote_InstanceProvider *pProvider )
474 remote_ContextImpl *p = (remote_ContextImpl * )
475 ContextAdmin::getInstance()->createAndRegisterContext(
476 pConnection ,
477 pIdStr ,
478 pDescription,
479 pProtocol,
480 pProvider );
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 );