1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svl.hxx"
30 
31 #include "ostreamcontainer.hxx"
32 
33 
34 using namespace ::com::sun::star;
35 
36 //-----------------------------------------------
37 OFSStreamContainer::OFSStreamContainer( const uno::Reference < io::XStream >& xStream )
38 : m_bDisposed( sal_False )
39 , m_bInputClosed( sal_False )
40 , m_bOutputClosed( sal_False )
41 , m_pListenersContainer( NULL )
42 , m_pTypeCollection( NULL )
43 {
44 	try
45 	{
46 		m_xStream = xStream;
47 		if ( !m_xStream.is() )
48 			throw uno::RuntimeException();
49 
50 		m_xSeekable = uno::Reference< io::XSeekable >( xStream, uno::UNO_QUERY );
51 		m_xInputStream = xStream->getInputStream();
52 		m_xOutputStream = xStream->getOutputStream();
53 		m_xTruncate = uno::Reference< io::XTruncate >( m_xOutputStream, uno::UNO_QUERY );
54 		m_xAsyncOutputMonitor = uno::Reference< io::XAsyncOutputMonitor >( m_xOutputStream, uno::UNO_QUERY );
55 	}
56 	catch( uno::Exception& )
57 	{
58 		m_xStream = uno::Reference< io::XStream >();
59 		m_xSeekable = uno::Reference< io::XSeekable >();
60 		m_xInputStream = uno::Reference< io::XInputStream >();
61 		m_xOutputStream = uno::Reference< io::XOutputStream >();
62 		m_xTruncate = uno::Reference< io::XTruncate >();
63 		m_xAsyncOutputMonitor = uno::Reference< io::XAsyncOutputMonitor >();
64 	}
65 }
66 
67 //-----------------------------------------------
68 OFSStreamContainer::~OFSStreamContainer()
69 {
70 	if ( m_pListenersContainer )
71 	{
72 		delete m_pListenersContainer;
73 		m_pListenersContainer = NULL;
74 	}
75 }
76 
77 // XInterface
78 //-----------------------------------------------
79 uno::Any SAL_CALL OFSStreamContainer::queryInterface( const uno::Type& rType )
80 		throw( uno::RuntimeException )
81 {
82 	uno::Any aReturn;
83 
84 	aReturn <<= ::cppu::queryInterface
85 				(	rType
86 					,	static_cast<lang::XTypeProvider*> ( this )
87 					,	static_cast<io::XStream*> ( this )
88 					,	static_cast<embed::XExtendedStorageStream*> ( this )
89 					,	static_cast<lang::XComponent*> ( this ) );
90 
91 	if ( aReturn.hasValue() == sal_True )
92 		return aReturn ;
93 
94 	if ( m_xSeekable.is() )
95 	{
96 		aReturn <<= ::cppu::queryInterface
97 				(	rType
98 					,	static_cast<io::XSeekable*> ( this ) );
99 
100 		if ( aReturn.hasValue() == sal_True )
101 			return aReturn ;
102 	}
103 
104 	if ( m_xInputStream.is() )
105 	{
106 		aReturn <<= ::cppu::queryInterface
107 				(	rType
108 					,	static_cast<io::XInputStream*> ( this ) );
109 
110 		if ( aReturn.hasValue() == sal_True )
111 			return aReturn ;
112 	}
113 	if ( m_xOutputStream.is() )
114 	{
115 		aReturn <<= ::cppu::queryInterface
116 				(	rType
117 					,	static_cast<io::XOutputStream*> ( this ) );
118 
119 		if ( aReturn.hasValue() == sal_True )
120 			return aReturn ;
121 	}
122 	if ( m_xTruncate.is() )
123 	{
124 		aReturn <<= ::cppu::queryInterface
125 				(	rType
126 					,	static_cast<io::XTruncate*> ( this ) );
127 
128 		if ( aReturn.hasValue() == sal_True )
129 			return aReturn ;
130 	}
131 	if ( m_xAsyncOutputMonitor.is() )
132 	{
133 		aReturn <<= ::cppu::queryInterface
134 				(	rType
135 					,	static_cast<io::XAsyncOutputMonitor*> ( this ) );
136 
137 		if ( aReturn.hasValue() == sal_True )
138 			return aReturn ;
139 	}
140 
141 	return OWeakObject::queryInterface( rType );
142 }
143 
144 //-----------------------------------------------
145 void SAL_CALL OFSStreamContainer::acquire()
146 		throw()
147 {
148 	OWeakObject::acquire();
149 }
150 
151 //-----------------------------------------------
152 void SAL_CALL OFSStreamContainer::release()
153 		throw()
154 {
155 	OWeakObject::release();
156 }
157 
158 //	XTypeProvider
159 //-----------------------------------------------
160 uno::Sequence< uno::Type > SAL_CALL OFSStreamContainer::getTypes()
161 		throw( uno::RuntimeException )
162 {
163 	if ( m_pTypeCollection == NULL )
164 	{
165 		::osl::MutexGuard aGuard( m_aMutex );
166 
167 		if ( m_pTypeCollection == NULL )
168 		{
169 			::cppu::OTypeCollection aTypeCollection
170 									(	::getCppuType( ( const uno::Reference< lang::XTypeProvider >* )NULL )
171 									,	::getCppuType( ( const uno::Reference< embed::XExtendedStorageStream >* )NULL ) );
172 
173 			if ( m_xSeekable.is() )
174 				aTypeCollection = ::cppu::OTypeCollection
175 									(	::getCppuType( ( const uno::Reference< io::XSeekable >* )NULL ),
176 										aTypeCollection.getTypes() );
177 			if ( m_xInputStream.is() )
178 				aTypeCollection = ::cppu::OTypeCollection
179 									(	::getCppuType( ( const uno::Reference< io::XInputStream >* )NULL ),
180 										aTypeCollection.getTypes() );
181 
182 			if ( m_xOutputStream.is() )
183 				aTypeCollection = ::cppu::OTypeCollection
184 									(	::getCppuType( ( const uno::Reference< io::XOutputStream >* )NULL ),
185 										aTypeCollection.getTypes() );
186 			if ( m_xTruncate.is() )
187 				aTypeCollection = ::cppu::OTypeCollection
188 									(	::getCppuType( ( const uno::Reference< io::XTruncate >* )NULL ),
189 										aTypeCollection.getTypes() );
190 			if ( m_xAsyncOutputMonitor.is() )
191 				aTypeCollection = ::cppu::OTypeCollection
192 									(	::getCppuType( ( const uno::Reference< io::XAsyncOutputMonitor >* )NULL ),
193 										aTypeCollection.getTypes() );
194 
195 			m_pTypeCollection = new ::cppu::OTypeCollection( aTypeCollection );
196 		}
197 	}
198 	return m_pTypeCollection->getTypes() ;
199 }
200 
201 //-----------------------------------------------
202 uno::Sequence< sal_Int8 > SAL_CALL OFSStreamContainer::getImplementationId()
203 		throw( uno::RuntimeException )
204 {
205 	static ::cppu::OImplementationId* pID = NULL ;
206 
207 	if ( pID == NULL )
208 	{
209 		::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ) ;
210 
211 		if ( pID == NULL )
212 		{
213 			static ::cppu::OImplementationId aID( sal_False ) ;
214 			pID = &aID ;
215 		}
216 	}
217 
218 	return pID->getImplementationId() ;
219 }
220 
221 // XStream
222 //-----------------------------------------------
223 uno::Reference< io::XInputStream > SAL_CALL OFSStreamContainer::getInputStream()
224 		throw ( uno::RuntimeException )
225 {
226 	::osl::MutexGuard aGuard( m_aMutex );
227 
228 	if ( m_bDisposed )
229 		throw lang::DisposedException();
230 
231 	if ( !m_xStream.is() )
232 		throw uno::RuntimeException();
233 
234 	if ( m_xInputStream.is() )
235 		return uno::Reference< io::XInputStream >( static_cast< io::XInputStream* >( this ) );
236 
237 	return uno::Reference< io::XInputStream >();
238 }
239 
240 //-----------------------------------------------
241 uno::Reference< io::XOutputStream > SAL_CALL OFSStreamContainer::getOutputStream()
242 		throw ( uno::RuntimeException )
243 {
244 	::osl::MutexGuard aGuard( m_aMutex );
245 
246 	if ( m_bDisposed )
247 		throw lang::DisposedException();
248 
249 	if ( !m_xStream.is() )
250 		throw uno::RuntimeException();
251 
252 	if ( m_xOutputStream.is() )
253 		return uno::Reference< io::XOutputStream >( static_cast< io::XOutputStream* >( this ) );
254 
255 	return uno::Reference< io::XOutputStream >();
256 }
257 
258 // XComponent
259 //-----------------------------------------------
260 void SAL_CALL OFSStreamContainer::dispose()
261 		throw ( uno::RuntimeException )
262 {
263 	::osl::MutexGuard aGuard( m_aMutex );
264 
265 	if ( m_bDisposed )
266 		throw lang::DisposedException();
267 
268 	if ( !m_xStream.is() )
269 		throw uno::RuntimeException();
270 
271 	if ( m_xInputStream.is() && !m_bInputClosed )
272 	{
273 		m_xInputStream->closeInput();
274 		m_bInputClosed = sal_True;
275 	}
276 
277 	if ( m_xOutputStream.is() && !m_bOutputClosed )
278 	{
279 		m_xOutputStream->closeOutput();
280 		m_bOutputClosed = sal_True;
281 	}
282 
283 	if ( m_pListenersContainer )
284 	{
285     	lang::EventObject aSource( static_cast< ::cppu::OWeakObject*>( this ) );
286 		m_pListenersContainer->disposeAndClear( aSource );
287 	}
288 
289 	m_bDisposed = sal_True;
290 }
291 
292 //-----------------------------------------------
293 void SAL_CALL OFSStreamContainer::addEventListener( const uno::Reference< lang::XEventListener >& xListener )
294 		throw ( uno::RuntimeException )
295 {
296 	::osl::MutexGuard aGuard( m_aMutex );
297 
298 	if ( m_bDisposed )
299 		throw lang::DisposedException();
300 
301 	if ( !m_pListenersContainer )
302 		m_pListenersContainer = new ::cppu::OInterfaceContainerHelper( m_aMutex );
303 
304 	m_pListenersContainer->addInterface( xListener );
305 }
306 
307 //-----------------------------------------------
308 void SAL_CALL OFSStreamContainer::removeEventListener( const uno::Reference< lang::XEventListener >& xListener )
309 		throw ( uno::RuntimeException )
310 {
311 	::osl::MutexGuard aGuard( m_aMutex );
312 
313 	if ( m_bDisposed )
314 		throw lang::DisposedException();
315 
316 	if ( m_pListenersContainer )
317 		m_pListenersContainer->removeInterface( xListener );
318 }
319 
320 
321 // XSeekable
322 //-----------------------------------------------
323 void SAL_CALL OFSStreamContainer::seek( sal_Int64 location )
324 		throw ( lang::IllegalArgumentException,
325 				io::IOException,
326 				uno::RuntimeException )
327 {
328 	::osl::MutexGuard aGuard( m_aMutex );
329 
330 	if ( m_bDisposed )
331 		throw lang::DisposedException();
332 
333 	if ( !m_xStream.is() || !m_xSeekable.is() )
334 		throw uno::RuntimeException();
335 
336 	m_xSeekable->seek( location );
337 }
338 
339 //-----------------------------------------------
340 sal_Int64 SAL_CALL OFSStreamContainer::getPosition()
341 		throw ( io::IOException,
342 				uno::RuntimeException )
343 {
344 	::osl::MutexGuard aGuard( m_aMutex );
345 
346 	if ( m_bDisposed )
347 		throw lang::DisposedException();
348 
349 	if ( !m_xStream.is() || !m_xSeekable.is() )
350 		throw uno::RuntimeException();
351 
352 	return m_xSeekable->getPosition();
353 }
354 
355 //-----------------------------------------------
356 sal_Int64 SAL_CALL OFSStreamContainer::getLength()
357 		throw ( io::IOException,
358 				uno::RuntimeException )
359 {
360 	::osl::MutexGuard aGuard( m_aMutex );
361 
362 	if ( m_bDisposed )
363 		throw lang::DisposedException();
364 
365 	if ( !m_xStream.is() || !m_xSeekable.is() )
366 		throw uno::RuntimeException();
367 
368 	return m_xSeekable->getLength();
369 }
370 
371 
372 // XInputStream
373 //-----------------------------------------------
374 sal_Int32 SAL_CALL OFSStreamContainer::readBytes( uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead )
375 		throw( io::NotConnectedException,
376 				io::BufferSizeExceededException,
377 				io::IOException,
378 				uno::RuntimeException )
379 {
380 	::osl::MutexGuard aGuard( m_aMutex );
381 
382 	if ( m_bDisposed )
383 		throw lang::DisposedException();
384 
385 	if ( !m_xStream.is() || !m_xInputStream.is() )
386 		throw uno::RuntimeException();
387 
388 	return m_xInputStream->readBytes( aData, nBytesToRead );
389 }
390 
391 //-----------------------------------------------
392 sal_Int32 SAL_CALL OFSStreamContainer::readSomeBytes( uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead )
393 		throw( io::NotConnectedException,
394 				io::BufferSizeExceededException,
395 				io::IOException,
396 				uno::RuntimeException )
397 {
398 	::osl::MutexGuard aGuard( m_aMutex );
399 
400 	if ( m_bDisposed )
401 		throw lang::DisposedException();
402 
403 	if ( !m_xStream.is() || !m_xInputStream.is() )
404 		throw uno::RuntimeException();
405 
406 	return m_xInputStream->readSomeBytes( aData, nMaxBytesToRead );
407 }
408 
409 //-----------------------------------------------
410 void SAL_CALL OFSStreamContainer::skipBytes( sal_Int32 nBytesToSkip )
411 		throw( io::NotConnectedException,
412 				io::BufferSizeExceededException,
413 				io::IOException,
414 				uno::RuntimeException )
415 {
416 	::osl::MutexGuard aGuard( m_aMutex );
417 
418 	if ( m_bDisposed )
419 		throw lang::DisposedException();
420 
421 	if ( !m_xStream.is() || !m_xInputStream.is() )
422 		throw uno::RuntimeException();
423 
424 	m_xInputStream->skipBytes( nBytesToSkip );
425 }
426 
427 //-----------------------------------------------
428 sal_Int32 SAL_CALL OFSStreamContainer::available()
429 		throw( io::NotConnectedException,
430 				io::IOException,
431 				uno::RuntimeException )
432 {
433 	::osl::MutexGuard aGuard( m_aMutex );
434 
435 	if ( m_bDisposed )
436 		throw lang::DisposedException();
437 
438 	if ( !m_xStream.is() || !m_xInputStream.is() )
439 		throw uno::RuntimeException();
440 
441 	return m_xInputStream->available();
442 }
443 
444 //-----------------------------------------------
445 void SAL_CALL OFSStreamContainer::closeInput()
446 		throw( io::NotConnectedException,
447 				io::IOException,
448 				uno::RuntimeException )
449 {
450 	::osl::MutexGuard aGuard( m_aMutex );
451 
452 	if ( m_bDisposed )
453 		throw lang::DisposedException();
454 
455 	if ( !m_xStream.is() || !m_xInputStream.is() )
456 		throw uno::RuntimeException();
457 
458 	if ( m_xInputStream.is() )
459 	{
460 		m_xInputStream->closeInput();
461 		m_bInputClosed = sal_True;
462 	}
463 
464 	if ( m_bOutputClosed )
465 		dispose();
466 }
467 
468 // XOutputStream
469 //-----------------------------------------------
470 void SAL_CALL OFSStreamContainer::writeBytes( const uno::Sequence< sal_Int8 >& aData )
471 		throw ( io::NotConnectedException,
472 				io::BufferSizeExceededException,
473 				io::IOException,
474 				uno::RuntimeException )
475 {
476 	::osl::MutexGuard aGuard( m_aMutex );
477 
478 	if ( m_bDisposed )
479 		throw lang::DisposedException();
480 
481 	if ( !m_xStream.is() || !m_xOutputStream.is() )
482 		throw uno::RuntimeException();
483 
484 	return m_xOutputStream->writeBytes( aData );
485 }
486 
487 //-----------------------------------------------
488 void SAL_CALL OFSStreamContainer::flush()
489 		throw ( io::NotConnectedException,
490 				io::BufferSizeExceededException,
491 				io::IOException,
492 				uno::RuntimeException )
493 {
494 	::osl::MutexGuard aGuard( m_aMutex );
495 
496 	if ( m_bDisposed )
497 		throw lang::DisposedException();
498 
499 	if ( !m_xStream.is() || !m_xOutputStream.is() )
500 		throw uno::RuntimeException();
501 
502 	return m_xOutputStream->flush();
503 }
504 
505 //-----------------------------------------------
506 void SAL_CALL OFSStreamContainer::closeOutput()
507 		throw ( io::NotConnectedException,
508 				io::BufferSizeExceededException,
509 				io::IOException,
510 				uno::RuntimeException )
511 {
512 	::osl::MutexGuard aGuard( m_aMutex );
513 
514 	if ( m_bDisposed )
515 		throw lang::DisposedException();
516 
517 	if ( !m_xStream.is() || !m_xOutputStream.is() )
518 		throw uno::RuntimeException();
519 
520 	if ( m_xOutputStream.is() )
521 	{
522 		m_xOutputStream->closeOutput();
523 		m_bOutputClosed = sal_True;
524 	}
525 
526 	if ( m_bInputClosed )
527 		dispose();
528 }
529 
530 
531 // XTruncate
532 //-----------------------------------------------
533 void SAL_CALL OFSStreamContainer::truncate()
534 		throw ( io::IOException,
535 				uno::RuntimeException )
536 {
537 	::osl::MutexGuard aGuard( m_aMutex );
538 
539 	if ( m_bDisposed )
540 		throw lang::DisposedException();
541 
542 	if ( !m_xStream.is() || !m_xTruncate.is() )
543 		throw uno::RuntimeException();
544 
545 	m_xTruncate->truncate();
546 }
547 
548 
549 // XAsyncOutputMonitor
550 //-----------------------------------------------
551 void SAL_CALL OFSStreamContainer::waitForCompletion()
552 		throw ( io::IOException,
553 				uno::RuntimeException )
554 {
555 	::osl::MutexGuard aGuard( m_aMutex );
556 
557 	if ( m_bDisposed )
558 		throw lang::DisposedException();
559 
560 	if ( !m_xStream.is() || !m_xAsyncOutputMonitor.is() )
561 		throw uno::RuntimeException();
562 
563 	m_xAsyncOutputMonitor->waitForCompletion();
564 }
565 
566 
567 
568