Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include "acceptor.hxx"
31 : : #include <unotools/bootstrap.hxx>
32 : : #include <tools/stream.hxx>
33 : : #include <vcl/svapp.hxx>
34 : : #include <com/sun/star/beans/XPropertySet.hpp>
35 : : #include <com/sun/star/uno/XNamingService.hpp>
36 : :
37 : : #include <cppuhelper/factory.hxx>
38 : :
39 : : namespace desktop
40 : : {
41 : :
42 : 158 : extern "C" void workerfunc (void * acc)
43 : : {
44 : 158 : ((Acceptor*)acc)->run();
45 : 158 : }
46 : :
47 : 254 : static Reference<XInterface> getComponentContext( const Reference<XMultiServiceFactory>& rFactory)
48 : : {
49 : 254 : Reference<XInterface> rContext;
50 [ + - ]: 254 : Reference< XPropertySet > rPropSet( rFactory, UNO_QUERY );
51 [ + - ]: 254 : Any a = rPropSet->getPropertyValue(
52 [ + - ]: 254 : ::rtl::OUString( "DefaultContext" ) );
53 [ + - ]: 254 : a >>= rContext;
54 : 254 : return rContext;
55 : : }
56 : :
57 : 158 : Mutex Acceptor::m_aMutex;
58 : :
59 : 158 : Acceptor::Acceptor( const Reference< XMultiServiceFactory >& rFactory )
60 : : : m_thread(NULL)
61 : : , m_aAcceptString()
62 : : , m_aConnectString()
63 : : , m_aProtocol()
64 : : , m_bInit(sal_False)
65 [ + - ][ + - ]: 158 : , m_bDying(false)
66 : : {
67 [ + - ]: 158 : m_rSMgr = rFactory;
68 [ + - ]: 158 : m_rAcceptor = Reference< XAcceptor > (m_rSMgr->createInstance(
69 : 158 : rtl::OUString("com.sun.star.connection.Acceptor" )),
70 [ + - ][ + - ]: 158 : UNO_QUERY );
[ + - ]
71 [ + - ]: 158 : m_rBridgeFactory = Reference < XBridgeFactory > (m_rSMgr->createInstance(
72 : 158 : rtl::OUString("com.sun.star.bridge.BridgeFactory" )),
73 [ + - ][ + - ]: 158 : UNO_QUERY );
[ + - ]
74 : : // get component context
75 [ + - ][ + - ]: 158 : m_rContext = getComponentContext(m_rSMgr);
76 : 158 : }
77 : :
78 : :
79 [ + - ]: 158 : Acceptor::~Acceptor()
80 : : {
81 [ + - ][ + - ]: 158 : m_rAcceptor->stopAccepting();
82 : : oslThread t;
83 : : {
84 [ + - ]: 158 : osl::MutexGuard g(m_aMutex);
85 [ + - ]: 158 : t = m_thread;
86 : : }
87 : : //prevent locking if the thread is still waiting
88 : 158 : m_bDying = true;
89 [ + - ]: 158 : m_cEnable.set();
90 [ + - ]: 158 : osl_joinWithThread(t);
91 [ + - ]: 158 : osl_destroyThread(t);
92 : : {
93 : : // Make the final state of m_bridges visible to this thread (since
94 : : // m_thread is joined, the code that follows is the only one left
95 : : // accessing m_bridges):
96 [ + - ][ + - ]: 158 : osl::MutexGuard g(m_aMutex);
97 : : }
98 : 96 : for (;;) {
99 : : com::sun::star::uno::Reference< com::sun::star::bridge::XBridge > b(
100 [ + - ]: 254 : m_bridges.remove());
101 [ + + ]: 254 : if (!b.is()) {
102 : : break;
103 : : }
104 : : com::sun::star::uno::Reference< com::sun::star::lang::XComponent >(
105 [ + - ][ + - ]: 350 : b, com::sun::star::uno::UNO_QUERY_THROW)->dispose();
[ + - ][ + + ]
106 : 254 : }
107 [ - + ]: 316 : }
108 : :
109 : 158 : void SAL_CALL Acceptor::run()
110 : : {
111 [ + - ][ + - ]: 254 : while ( m_rAcceptor.is() && m_rBridgeFactory.is() )
[ + - ]
112 : : {
113 : : RTL_LOGFILE_CONTEXT( aLog, "desktop (lo119109) Acceptor::run" );
114 : : try
115 : : {
116 : : // wait until we get enabled
117 : : RTL_LOGFILE_CONTEXT_TRACE( aLog, "desktop (lo119109)"\
118 : : "Acceptor::run waiting for office to come up");
119 [ + - ]: 254 : m_cEnable.wait();
120 [ + + ]: 254 : if (m_bDying) //see destructor
121 : : break;
122 : : RTL_LOGFILE_CONTEXT_TRACE( aLog, "desktop (lo119109)"\
123 : : "Acceptor::run now enabled and continuing");
124 : :
125 : : // accept connection
126 [ + - ][ + - ]: 192 : Reference< XConnection > rConnection = m_rAcceptor->accept( m_aConnectString );
127 : : // if we return without a valid connection we mus assume that the acceptor
128 : : // is destructed so we break out of the run method terminating the thread
129 [ + + ]: 192 : if (! rConnection.is()) break;
130 [ + - ][ + - ]: 96 : OUString aDescription = rConnection->getDescription();
131 : : RTL_LOGFILE_CONTEXT_TRACE1( aLog, "desktop (lo119109) Acceptor::run connection %s",
132 : : OUStringToOString(aDescription, RTL_TEXTENCODING_ASCII_US).getStr());
133 : :
134 : : // create instanceprovider for this connection
135 : : Reference< XInstanceProvider > rInstanceProvider(
136 [ + - ][ + - ]: 96 : (XInstanceProvider*)new AccInstanceProvider(m_rSMgr, rConnection));
[ + - ]
137 : : // create the bridge. The remote end will have a reference to this bridge
138 : : // thus preventing the bridge from being disposed. When the remote end releases
139 : : // the bridge, it will be destructed.
140 [ + - ]: 96 : Reference< XBridge > rBridge = m_rBridgeFactory->createBridge(
141 [ + - ]: 96 : rtl::OUString() ,m_aProtocol ,rConnection ,rInstanceProvider );
142 [ + - ]: 96 : osl::MutexGuard g(m_aMutex);
143 [ + - ][ + - ]: 254 : m_bridges.add(rBridge);
[ + + ][ # # ]
144 : 0 : } catch (const Exception&) {
145 : : // connection failed...
146 : : // something went wrong during connection setup.
147 : : // just wait for a new connection to accept
148 : : }
149 : : }
150 : 158 : }
151 : :
152 : : // XInitialize
153 : 254 : void SAL_CALL Acceptor::initialize( const Sequence<Any>& aArguments )
154 : : throw( Exception )
155 : : {
156 : : // prevent multiple initialization
157 [ + - ]: 254 : ClearableMutexGuard aGuard( m_aMutex );
158 : : RTL_LOGFILE_CONTEXT( aLog, "destop (lo119109) Acceptor::initialize()" );
159 : :
160 : 254 : sal_Bool bOk = sal_False;
161 : :
162 : : // arg count
163 : 254 : int nArgs = aArguments.getLength();
164 : :
165 : : // not yet initialized and acceptstring
166 [ + - ][ + - ]: 254 : if (!m_bInit && nArgs > 0 && (aArguments[0] >>= m_aAcceptString))
[ + + ][ + + ]
167 : : {
168 : : RTL_LOGFILE_CONTEXT_TRACE1( aLog, "desktop (lo119109) Acceptor::initialize string=%s",
169 : : OUStringToOString(m_aAcceptString, RTL_TEXTENCODING_ASCII_US).getStr());
170 : :
171 : : // get connect string and protocol from accept string
172 : : // "<connectString>;<protocol>"
173 : 158 : sal_Int32 nIndex1 = m_aAcceptString.indexOf( (sal_Unicode) ';' );
174 [ - + ]: 158 : if (nIndex1 < 0) throw IllegalArgumentException(
175 [ # # ]: 0 : OUString("Invalid accept-string format"), m_rContext, 1);
176 : 158 : m_aConnectString = m_aAcceptString.copy( 0 , nIndex1 ).trim();
177 : 158 : nIndex1++;
178 : 158 : sal_Int32 nIndex2 = m_aAcceptString.indexOf( (sal_Unicode) ';' , nIndex1 );
179 [ + - ]: 158 : if (nIndex2 < 0) nIndex2 = m_aAcceptString.getLength();
180 : 158 : m_aProtocol = m_aAcceptString.copy( nIndex1, nIndex2 - nIndex1 );
181 : :
182 : : // start accepting in new thread...
183 [ + - ]: 158 : m_thread = osl_createThread(workerfunc, this);
184 : 158 : m_bInit = sal_True;
185 : 158 : bOk = sal_True;
186 : : }
187 : :
188 : : // do we want to enable accepting?
189 : 254 : sal_Bool bEnable = sal_False;
190 [ + + ][ - + ]: 412 : if (((nArgs == 1 && (aArguments[0] >>= bEnable)) ||
[ + - + - ]
[ + + ][ + + ]
191 : 158 : (nArgs == 2 && (aArguments[1] >>= bEnable))) &&
192 : : bEnable )
193 : : {
194 [ + - ]: 96 : m_cEnable.set();
195 : 96 : bOk = sal_True;
196 : : }
197 : :
198 [ - + ]: 254 : if (!bOk)
199 : : {
200 : : throw IllegalArgumentException(
201 [ # # ]: 0 : OUString("invalid initialization"), m_rContext, 1);
202 [ + - ]: 254 : }
203 : 254 : }
204 : :
205 : : // XServiceInfo
206 : : const sal_Char *Acceptor::serviceName = "com.sun.star.office.Acceptor";
207 : : const sal_Char *Acceptor::implementationName = "com.sun.star.office.comp.Acceptor";
208 : : const sal_Char *Acceptor::supportedServiceNames[] = {"com.sun.star.office.Acceptor", NULL};
209 : 316 : OUString Acceptor::impl_getImplementationName()
210 : : {
211 : 316 : return OUString::createFromAscii( implementationName );
212 : : }
213 : 0 : OUString SAL_CALL Acceptor::getImplementationName()
214 : : throw (RuntimeException)
215 : : {
216 : 0 : return Acceptor::impl_getImplementationName();
217 : : }
218 : 158 : Sequence<OUString> Acceptor::impl_getSupportedServiceNames()
219 : : {
220 : 158 : Sequence<OUString> aSequence;
221 [ + + ]: 316 : for (int i=0; supportedServiceNames[i]!=NULL; i++) {
222 [ + - ]: 158 : aSequence.realloc(i+1);
223 [ + - ]: 158 : aSequence[i]=(OUString::createFromAscii(supportedServiceNames[i]));
224 : : }
225 : 158 : return aSequence;
226 : : }
227 : 0 : Sequence<OUString> SAL_CALL Acceptor::getSupportedServiceNames()
228 : : throw (RuntimeException)
229 : : {
230 : 0 : return Acceptor::impl_getSupportedServiceNames();
231 : : }
232 : 0 : sal_Bool SAL_CALL Acceptor::supportsService( const OUString&)
233 : : throw (RuntimeException)
234 : : {
235 : 0 : return sal_False;
236 : : }
237 : :
238 : : // Factory
239 : 158 : Reference< XInterface > Acceptor::impl_getInstance( const Reference< XMultiServiceFactory >& aFactory )
240 : : {
241 : : try {
242 [ + - ][ + - ]: 158 : return (XComponent*) new Acceptor( aFactory );
243 [ # # ]: 0 : } catch ( const Exception& ) {
244 [ # # ]: 0 : return (XComponent*) NULL;
245 : : }
246 : : }
247 : :
248 : : // InstanceProvider
249 : 96 : AccInstanceProvider::AccInstanceProvider(const Reference<XMultiServiceFactory>& aFactory, const Reference<XConnection>& rConnection)
250 : : {
251 [ + - ]: 96 : m_rSMgr = aFactory;
252 [ + - ]: 96 : m_rConnection = rConnection;
253 : 96 : }
254 : :
255 : 94 : AccInstanceProvider::~AccInstanceProvider()
256 : : {
257 [ - + ]: 188 : }
258 : :
259 : 130 : Reference<XInterface> SAL_CALL AccInstanceProvider::getInstance (const OUString& aName )
260 : : throw ( NoSuchElementException )
261 : : {
262 : :
263 : 130 : Reference<XInterface> rInstance;
264 : :
265 [ + + ]: 130 : if ( aName.compareToAscii( "StarOffice.ServiceManager" ) == 0)
266 : : {
267 [ + - ]: 34 : rInstance = Reference< XInterface >( m_rSMgr );
268 : : }
269 [ + - ]: 96 : else if(aName.compareToAscii( "StarOffice.ComponentContext" ) == 0 )
270 : : {
271 [ + - ][ + - ]: 96 : rInstance = getComponentContext( m_rSMgr );
272 : : }
273 [ # # ]: 0 : else if ( aName.compareToAscii("StarOffice.NamingService" ) == 0 )
274 : : {
275 : : Reference< XNamingService > rNamingService(
276 [ # # ]: 0 : m_rSMgr->createInstance( OUString("com.sun.star.uno.NamingService" )),
277 [ # # ][ # # ]: 0 : UNO_QUERY );
278 [ # # ]: 0 : if ( rNamingService.is() )
279 : : {
280 [ # # ]: 0 : rNamingService->registerObject(
281 [ # # ]: 0 : OUString("StarOffice.ServiceManager" ), m_rSMgr );
282 [ # # ]: 0 : rNamingService->registerObject(
283 [ # # ][ # # ]: 0 : OUString("StarOffice.ComponentContext" ), getComponentContext( m_rSMgr ));
284 [ # # ]: 0 : rInstance = rNamingService;
285 : 0 : }
286 : : }
287 : 130 : return rInstance;
288 : : }
289 : :
290 : : }
291 : :
292 : : // component management stuff...
293 : : // ----------------------------------------------------------------------------
294 : : extern "C"
295 : : {
296 : : using namespace desktop;
297 : :
298 : 158 : SAL_DLLPUBLIC_EXPORT void * SAL_CALL offacc_component_getFactory(const sal_Char *pImplementationName, void *pServiceManager, void *)
299 : : {
300 : 158 : void* pReturn = NULL ;
301 [ + - ][ + - ]: 158 : if ( pImplementationName && pServiceManager )
302 : : {
303 : : // Define variables which are used in following macros.
304 : 158 : Reference< XSingleServiceFactory > xFactory;
305 : : Reference< XMultiServiceFactory > xServiceManager(
306 [ + - ]: 158 : reinterpret_cast< XMultiServiceFactory* >(pServiceManager));
307 : :
308 [ + - ]: 158 : if (Acceptor::impl_getImplementationName().compareToAscii( pImplementationName ) == COMPARE_EQUAL )
309 : : {
310 : : xFactory = Reference< XSingleServiceFactory >( cppu::createSingleFactory(
311 : : xServiceManager, Acceptor::impl_getImplementationName(),
312 [ + - ][ + - ]: 158 : Acceptor::impl_getInstance, Acceptor::impl_getSupportedServiceNames()) );
[ + - ][ + - ]
313 : : }
314 : :
315 : : // Factory is valid - service was found.
316 [ + - ]: 158 : if ( xFactory.is() )
317 : : {
318 [ + - ]: 158 : xFactory->acquire();
319 [ + - ]: 158 : pReturn = xFactory.get();
320 : 158 : }
321 : : }
322 : :
323 : : // Return with result of this operation.
324 : 158 : return pReturn ;
325 : : }
326 : :
327 [ + - ][ + - ]: 474 : } // extern "C"
328 : :
329 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|