Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
5 : : * This Source Code Form is subject to the terms of the Mozilla Public
6 : : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
11 : : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : : * contributor license agreements. See the NOTICE file distributed
13 : : * with this work for additional information regarding copyright
14 : : * ownership. The ASF licenses this file to you under the Apache
15 : : * License, Version 2.0 (the "License"); you may not use this file
16 : : * except in compliance with the License. You may obtain a copy of
17 : : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : : */
19 : :
20 : :
21 : : #include <stdio.h>
22 : :
23 : : #include <osl/diagnose.h>
24 : :
25 : : #include <com/sun/star/io/XActiveDataSource.hpp>
26 : : #include <com/sun/star/io/XActiveDataSink.hpp>
27 : : #include <com/sun/star/io/XActiveDataControl.hpp>
28 : : #include <com/sun/star/io/XConnectable.hpp>
29 : : #include <com/sun/star/lang/XSingleServiceFactory.hpp>
30 : : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
31 : : #include <com/sun/star/lang/XServiceInfo.hpp>
32 : : #include <com/sun/star/registry/XRegistryKey.hpp>
33 : :
34 : : #include <uno/dispatcher.h>
35 : : #include <uno/mapping.hxx>
36 : : #include <cppuhelper/implbase5.hxx>
37 : : #include <cppuhelper/factory.hxx>
38 : : #include <cppuhelper/interfacecontainer.hxx>
39 : : #include <osl/mutex.hxx>
40 : : #include <osl/thread.h>
41 : :
42 : :
43 : : using namespace osl;
44 : : using namespace std;
45 : : using namespace cppu;
46 : : using namespace com::sun::star::uno;
47 : : using namespace com::sun::star::lang;
48 : : using namespace com::sun::star::registry;
49 : : using namespace com::sun::star::io;
50 : :
51 : : using ::rtl::OUString;
52 : : using ::rtl::OUStringToOString;
53 : : using ::rtl::OString;
54 : :
55 : : #include "factreg.hxx"
56 : :
57 : : namespace io_stm {
58 : :
59 : : class Pump : public WeakImplHelper5<
60 : : XActiveDataSource, XActiveDataSink, XActiveDataControl, XConnectable, XServiceInfo >
61 : : {
62 : : Mutex m_aMutex;
63 : : oslThread m_aThread;
64 : :
65 : : Reference< XConnectable > m_xPred;
66 : : Reference< XConnectable > m_xSucc;
67 : : Reference< XInputStream > m_xInput;
68 : : Reference< XOutputStream > m_xOutput;
69 : : OInterfaceContainerHelper m_cnt;
70 : : sal_Bool m_closeFired;
71 : :
72 : : void run();
73 : : static void static_run( void* pObject );
74 : :
75 : : void close();
76 : : void fireClose();
77 : : void fireStarted();
78 : : void fireTerminated();
79 : : void fireError( const Any &a );
80 : :
81 : : public:
82 : : Pump();
83 : : virtual ~Pump();
84 : :
85 : : // XActiveDataSource
86 : : virtual void SAL_CALL setOutputStream( const Reference< ::com::sun::star::io::XOutputStream >& xOutput ) throw();
87 : : virtual Reference< ::com::sun::star::io::XOutputStream > SAL_CALL getOutputStream() throw();
88 : :
89 : : // XActiveDataSink
90 : : virtual void SAL_CALL setInputStream( const Reference< ::com::sun::star::io::XInputStream >& xStream ) throw();
91 : : virtual Reference< ::com::sun::star::io::XInputStream > SAL_CALL getInputStream() throw();
92 : :
93 : : // XActiveDataControl
94 : : virtual void SAL_CALL addListener( const Reference< ::com::sun::star::io::XStreamListener >& xListener ) throw();
95 : : virtual void SAL_CALL removeListener( const Reference< ::com::sun::star::io::XStreamListener >& xListener ) throw();
96 : : virtual void SAL_CALL start() throw( RuntimeException );
97 : : virtual void SAL_CALL terminate() throw();
98 : :
99 : : // XConnectable
100 : : virtual void SAL_CALL setPredecessor( const Reference< ::com::sun::star::io::XConnectable >& xPred ) throw();
101 : : virtual Reference< ::com::sun::star::io::XConnectable > SAL_CALL getPredecessor() throw();
102 : : virtual void SAL_CALL setSuccessor( const Reference< ::com::sun::star::io::XConnectable >& xSucc ) throw();
103 : : virtual Reference< ::com::sun::star::io::XConnectable > SAL_CALL getSuccessor() throw();
104 : :
105 : : public: // XServiceInfo
106 : : virtual OUString SAL_CALL getImplementationName() throw( );
107 : : virtual Sequence< OUString > SAL_CALL getSupportedServiceNames(void) throw( );
108 : : virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw( );
109 : : };
110 : :
111 : 0 : Pump::Pump() : m_aThread( 0 ),
112 : : m_cnt( m_aMutex ),
113 [ # # ][ # # ]: 0 : m_closeFired( sal_False )
114 : : {
115 [ # # ]: 0 : g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
116 : 0 : }
117 : :
118 [ # # ][ # # ]: 0 : Pump::~Pump()
119 : : {
120 : : // exit gracefully
121 [ # # ]: 0 : if( m_aThread )
122 : : {
123 [ # # ]: 0 : osl_joinWithThread( m_aThread );
124 [ # # ]: 0 : osl_destroyThread( m_aThread );
125 : : }
126 [ # # ]: 0 : g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
127 [ # # ]: 0 : }
128 : :
129 : 0 : void Pump::fireError( const Any & exception )
130 : : {
131 [ # # ]: 0 : OInterfaceIteratorHelper iter( m_cnt );
132 [ # # ]: 0 : while( iter.hasMoreElements() )
133 : : {
134 : : try
135 : : {
136 [ # # ][ # # ]: 0 : static_cast< XStreamListener * > ( iter.next() )->error( exception );
137 : : }
138 [ # # # # ]: 0 : catch ( const RuntimeException &e )
139 : : {
140 [ # # ]: 0 : OString sMessage = OUStringToOString( e.Message , RTL_TEXTENCODING_ASCII_US );
141 : 0 : OSL_ENSURE( !"com.sun.star.comp.stoc.Pump: unexpected exception during calling listeners", sMessage.getStr() );
142 : : }
143 [ # # ]: 0 : }
144 : 0 : }
145 : :
146 : 0 : void Pump::fireClose()
147 : : {
148 : 0 : sal_Bool bFire = sal_False;
149 : : {
150 [ # # ]: 0 : MutexGuard guard( m_aMutex );
151 [ # # ]: 0 : if( ! m_closeFired )
152 : : {
153 : 0 : m_closeFired = sal_True;
154 : 0 : bFire = sal_True;
155 [ # # ]: 0 : }
156 : : }
157 : :
158 [ # # ]: 0 : if( bFire )
159 : : {
160 [ # # ]: 0 : OInterfaceIteratorHelper iter( m_cnt );
161 [ # # ]: 0 : while( iter.hasMoreElements() )
162 : : {
163 : : try
164 : : {
165 [ # # ][ # # ]: 0 : static_cast< XStreamListener * > ( iter.next() )->closed( );
166 : : }
167 [ # # # # ]: 0 : catch ( const RuntimeException &e )
168 : : {
169 [ # # ]: 0 : OString sMessage = OUStringToOString( e.Message , RTL_TEXTENCODING_ASCII_US );
170 : 0 : OSL_ENSURE( !"com.sun.star.comp.stoc.Pump: unexpected exception during calling listeners", sMessage.getStr() );
171 : : }
172 [ # # ]: 0 : }
173 : : }
174 : 0 : }
175 : :
176 : 0 : void Pump::fireStarted()
177 : : {
178 [ # # ]: 0 : OInterfaceIteratorHelper iter( m_cnt );
179 [ # # ]: 0 : while( iter.hasMoreElements() )
180 : : {
181 : : try
182 : : {
183 [ # # ][ # # ]: 0 : static_cast< XStreamListener * > ( iter.next() )->started( );
184 : : }
185 [ # # # # ]: 0 : catch ( const RuntimeException &e )
186 : : {
187 [ # # ]: 0 : OString sMessage = OUStringToOString( e.Message , RTL_TEXTENCODING_ASCII_US );
188 : 0 : OSL_ENSURE( !"com.sun.star.comp.stoc.Pump: unexpected exception during calling listeners", sMessage.getStr() );
189 : : }
190 [ # # ]: 0 : }
191 : 0 : }
192 : :
193 : 0 : void Pump::fireTerminated()
194 : : {
195 [ # # ]: 0 : OInterfaceIteratorHelper iter( m_cnt );
196 [ # # ]: 0 : while( iter.hasMoreElements() )
197 : : {
198 : : try
199 : : {
200 [ # # ][ # # ]: 0 : static_cast< XStreamListener * > ( iter.next() )->terminated();
201 : : }
202 [ # # # # ]: 0 : catch ( const RuntimeException &e )
203 : : {
204 [ # # ]: 0 : OString sMessage = OUStringToOString( e.Message , RTL_TEXTENCODING_ASCII_US );
205 : 0 : OSL_ENSURE( !"com.sun.star.comp.stoc.Pump: unexpected exception during calling listeners", sMessage.getStr() );
206 : : }
207 [ # # ]: 0 : }
208 : 0 : }
209 : :
210 : :
211 : :
212 : 0 : void Pump::close()
213 : : {
214 : : // close streams and release references
215 : 0 : Reference< XInputStream > rInput;
216 : 0 : Reference< XOutputStream > rOutput;
217 : : {
218 [ # # ]: 0 : MutexGuard guard( m_aMutex );
219 [ # # ]: 0 : rInput = m_xInput;
220 : 0 : m_xInput.clear();
221 : :
222 [ # # ]: 0 : rOutput = m_xOutput;
223 : 0 : m_xOutput.clear();
224 : 0 : m_xSucc.clear();
225 [ # # # # ]: 0 : m_xPred.clear();
226 : : }
227 [ # # ]: 0 : if( rInput.is() )
228 : : {
229 : : try
230 : : {
231 [ # # ][ # # ]: 0 : rInput->closeInput();
232 : : }
233 [ # # # # ]: 0 : catch( Exception & )
234 : : {
235 : : // go down calm
236 : : }
237 : : }
238 [ # # ]: 0 : if( rOutput.is() )
239 : : {
240 : : try
241 : : {
242 [ # # ][ # # ]: 0 : rOutput->closeOutput();
243 : : }
244 [ # # ]: 0 : catch( Exception & )
245 : : {
246 : : // go down calm
247 : : }
248 : 0 : }
249 : 0 : }
250 : :
251 : 0 : void Pump::static_run( void* pObject )
252 : : {
253 : 0 : ((Pump*)pObject)->run();
254 : 0 : ((Pump*)pObject)->release();
255 : 0 : }
256 : :
257 : 0 : void Pump::run()
258 : : {
259 : : try
260 : : {
261 [ # # ]: 0 : fireStarted();
262 : : try
263 : : {
264 : 0 : Reference< XInputStream > rInput;
265 : 0 : Reference< XOutputStream > rOutput;
266 : : {
267 [ # # ]: 0 : Guard< Mutex > aGuard( m_aMutex );
268 [ # # ]: 0 : rInput = m_xInput;
269 [ # # ][ # # ]: 0 : rOutput = m_xOutput;
270 : : }
271 : :
272 [ # # ]: 0 : if( ! rInput.is() )
273 : : {
274 : : NotConnectedException exception(
275 [ # # ][ # # ]: 0 : OUString(RTL_CONSTASCII_USTRINGPARAM("no input stream set")) , Reference<XInterface>((OWeakObject*)this) );
[ # # ]
276 [ # # ]: 0 : throw exception;
277 : : }
278 [ # # ]: 0 : Sequence< sal_Int8 > aData;
279 [ # # ][ # # ]: 0 : while( rInput->readSomeBytes( aData, 65536 ) )
[ # # ]
280 : : {
281 [ # # ]: 0 : if( ! rOutput.is() )
282 : : {
283 : : NotConnectedException exception(
284 [ # # ][ # # ]: 0 : OUString(RTL_CONSTASCII_USTRINGPARAM("no output stream set")) , Reference<XInterface>( (OWeakObject*)this) );
[ # # ]
285 [ # # ]: 0 : throw exception;
286 : : }
287 [ # # ][ # # ]: 0 : rOutput->writeBytes( aData );
288 [ # # ]: 0 : osl_yieldThread();
289 [ # # ]: 0 : }
290 : : }
291 [ # # ]: 0 : catch ( const IOException & e )
292 : : {
293 [ # # # # ]: 0 : fireError( makeAny( e ) );
294 : : }
295 [ # # ]: 0 : catch ( const RuntimeException & e )
296 : : {
297 [ # # # # ]: 0 : fireError( makeAny( e ) );
298 : : }
299 [ # # # # : 0 : catch ( const Exception & e )
# # ]
300 : : {
301 [ # # # # ]: 0 : fireError( makeAny( e ) );
302 : : }
303 : :
304 [ # # ]: 0 : close();
305 [ # # ]: 0 : fireClose();
306 : : }
307 [ # # ]: 0 : catch ( const com::sun::star::uno::Exception &e )
308 : : {
309 : : // we are the last on the stack.
310 : : // this is to avoid crashing the program, when e.g. a bridge crashes
311 [ # # ]: 0 : OString sMessage = OUStringToOString( e.Message , RTL_TEXTENCODING_ASCII_US );
312 : 0 : OSL_ENSURE( !"com.sun.star.comp.stoc.Pump: unexpected exception", sMessage.getStr() );
313 : : }
314 : 0 : }
315 : :
316 : : // ------------------------------------------------------------
317 : :
318 : : /*
319 : : * XConnectable
320 : : */
321 : :
322 : 0 : void Pump::setPredecessor( const Reference< XConnectable >& xPred ) throw()
323 : : {
324 [ # # ]: 0 : Guard< Mutex > aGuard( m_aMutex );
325 [ # # ][ # # ]: 0 : m_xPred = xPred;
326 : 0 : }
327 : :
328 : : // ------------------------------------------------------------
329 : :
330 : 0 : Reference< XConnectable > Pump::getPredecessor() throw()
331 : : {
332 [ # # ]: 0 : Guard< Mutex > aGuard( m_aMutex );
333 [ # # ]: 0 : return m_xPred;
334 : : }
335 : :
336 : : // ------------------------------------------------------------
337 : :
338 : 0 : void Pump::setSuccessor( const Reference< XConnectable >& xSucc ) throw()
339 : : {
340 [ # # ]: 0 : Guard< Mutex > aGuard( m_aMutex );
341 [ # # ][ # # ]: 0 : m_xSucc = xSucc;
342 : 0 : }
343 : :
344 : : // ------------------------------------------------------------
345 : :
346 : 0 : Reference< XConnectable > Pump::getSuccessor() throw()
347 : : {
348 [ # # ]: 0 : Guard< Mutex > aGuard( m_aMutex );
349 [ # # ]: 0 : return m_xSucc;
350 : : }
351 : :
352 : : // -----------------------------------------------------------------
353 : :
354 : : /*
355 : : * XActiveDataControl
356 : : */
357 : :
358 : 0 : void Pump::addListener( const Reference< XStreamListener >& xListener ) throw()
359 : : {
360 : 0 : m_cnt.addInterface( xListener );
361 : 0 : }
362 : :
363 : : // ------------------------------------------------------------
364 : :
365 : 0 : void Pump::removeListener( const Reference< XStreamListener >& xListener ) throw()
366 : : {
367 : 0 : m_cnt.removeInterface( xListener );
368 : 0 : }
369 : :
370 : : // ------------------------------------------------------------
371 : :
372 : 0 : void Pump::start() throw( RuntimeException )
373 : : {
374 [ # # ]: 0 : Guard< Mutex > aGuard( m_aMutex );
375 [ # # ]: 0 : m_aThread = osl_createSuspendedThread((oslWorkerFunction)Pump::static_run,this);
376 [ # # ]: 0 : if( m_aThread )
377 : : {
378 : : // will be released by OPump::static_run
379 : 0 : acquire();
380 [ # # ]: 0 : osl_resumeThread( m_aThread );
381 : : }
382 : : else
383 : : {
384 : : throw RuntimeException(
385 : : OUString( RTL_CONSTASCII_USTRINGPARAM( "Pump::start Couldn't create worker thread" )),
386 [ # # ][ # # ]: 0 : *this);
[ # # ]
387 [ # # ]: 0 : }
388 : 0 : }
389 : :
390 : : // ------------------------------------------------------------
391 : :
392 : 0 : void Pump::terminate() throw()
393 : : {
394 : 0 : close();
395 : :
396 : : // wait for the worker to die
397 [ # # ]: 0 : if( m_aThread )
398 : 0 : osl_joinWithThread( m_aThread );
399 : :
400 : 0 : fireTerminated();
401 : 0 : fireClose();
402 : 0 : }
403 : :
404 : : // ------------------------------------------------------------
405 : :
406 : : /*
407 : : * XActiveDataSink
408 : : */
409 : :
410 : 0 : void Pump::setInputStream( const Reference< XInputStream >& xStream ) throw()
411 : : {
412 [ # # ]: 0 : Guard< Mutex > aGuard( m_aMutex );
413 [ # # ]: 0 : m_xInput = xStream;
414 [ # # ]: 0 : Reference< XConnectable > xConnect( xStream, UNO_QUERY );
415 [ # # ]: 0 : if( xConnect.is() )
416 [ # # ][ # # ]: 0 : xConnect->setSuccessor( this );
[ # # ][ # # ]
417 : : // data transfer starts in XActiveDataControl::start
418 : 0 : }
419 : :
420 : : // ------------------------------------------------------------
421 : :
422 : 0 : Reference< XInputStream > Pump::getInputStream() throw()
423 : : {
424 [ # # ]: 0 : Guard< Mutex > aGuard( m_aMutex );
425 [ # # ]: 0 : return m_xInput;
426 : : }
427 : :
428 : : // ------------------------------------------------------------
429 : :
430 : : /*
431 : : * XActiveDataSource
432 : : */
433 : :
434 : 0 : void Pump::setOutputStream( const Reference< XOutputStream >& xOut ) throw()
435 : : {
436 [ # # ]: 0 : Guard< Mutex > aGuard( m_aMutex );
437 [ # # ]: 0 : m_xOutput = xOut;
438 [ # # ]: 0 : Reference< XConnectable > xConnect( xOut, UNO_QUERY );
439 [ # # ]: 0 : if( xConnect.is() )
440 [ # # ][ # # ]: 0 : xConnect->setPredecessor( this );
[ # # ][ # # ]
441 : : // data transfer starts in XActiveDataControl::start
442 : 0 : }
443 : :
444 : : // ------------------------------------------------------------
445 : :
446 : 0 : Reference< XOutputStream > Pump::getOutputStream() throw()
447 : : {
448 [ # # ]: 0 : Guard< Mutex > aGuard( m_aMutex );
449 [ # # ]: 0 : return m_xOutput;
450 : : }
451 : :
452 : :
453 : : // XServiceInfo
454 : 0 : OUString Pump::getImplementationName() throw( )
455 : : {
456 : 0 : return OPumpImpl_getImplementationName();
457 : : }
458 : :
459 : : // XServiceInfo
460 : 0 : sal_Bool Pump::supportsService(const OUString& ServiceName) throw( )
461 : : {
462 : 0 : Sequence< OUString > aSNL = getSupportedServiceNames();
463 : 0 : const OUString * pArray = aSNL.getConstArray();
464 : :
465 [ # # ]: 0 : for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
466 [ # # ]: 0 : if( pArray[i] == ServiceName )
467 : 0 : return sal_True;
468 : :
469 [ # # ]: 0 : return sal_False;
470 : : }
471 : :
472 : : // XServiceInfo
473 : 0 : Sequence< OUString > Pump::getSupportedServiceNames(void) throw( )
474 : : {
475 : 0 : return OPumpImpl_getSupportedServiceNames();
476 : : }
477 : :
478 : :
479 : 0 : Reference< XInterface > SAL_CALL OPumpImpl_CreateInstance(
480 : : SAL_UNUSED_PARAMETER const Reference< XComponentContext > & )
481 : : throw (Exception)
482 : : {
483 [ # # ]: 0 : return Reference< XInterface >( *new Pump );
484 : : }
485 : :
486 : 20 : OUString OPumpImpl_getImplementationName()
487 : : {
488 : 20 : return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.io.Pump") );
489 : : }
490 : :
491 : 0 : Sequence<OUString> OPumpImpl_getSupportedServiceNames(void)
492 : : {
493 [ # # ]: 0 : OUString s( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.io.Pump" ) );
494 [ # # ]: 0 : Sequence< OUString > seq( &s , 1 );
495 : 0 : return seq;
496 : : }
497 : :
498 : : }
499 : :
500 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|