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_sot.hxx"
30 #include <com/sun/star/lang/DisposedException.hpp>
31 #include <com/sun/star/io/XStream.hpp>
32 #include <com/sun/star/io/XInputStream.hpp>
33 #include <com/sun/star/io/XSeekable.hpp>
34 #include <com/sun/star/io/XTruncate.hpp>
35 
36 #include <comphelper/storagehelper.hxx>
37 
38 #include <unotools/ucbstreamhelper.hxx>
39 
40 #include <cppuhelper/exc_hlp.hxx>
41 
42 #include <sot/storinfo.hxx>
43 
44 #include "xolesimplestorage.hxx"
45 
46 
47 using namespace ::com::sun::star;
48 
49 const sal_Int32 nBytesCount = 32000;
50 
51 
52 // --------------------------------------------------------------------------------
53 OLESimpleStorage::OLESimpleStorage( uno::Reference< lang::XMultiServiceFactory > xFactory )
54 : m_bDisposed( sal_False )
55 , m_pStream( NULL )
56 , m_pStorage( NULL )
57 , m_pListenersContainer( NULL )
58 , m_xFactory( xFactory )
59 , m_bNoTemporaryCopy( sal_False )
60 {
61 	OSL_ENSURE( m_xFactory.is(), "No factory is provided on creation!\n" );
62 	if ( !m_xFactory.is() )
63 		throw uno::RuntimeException();
64 }
65 
66 // --------------------------------------------------------------------------------
67 OLESimpleStorage::~OLESimpleStorage()
68 {
69 	try {
70 		m_refCount++;
71 		dispose();
72 	} catch( uno::Exception& )
73 	{}
74 
75 	if ( m_pListenersContainer )
76 	{
77 		delete m_pListenersContainer;
78 		m_pListenersContainer = NULL;
79 	}
80 }
81 
82 //-------------------------------------------------------------------------
83 uno::Sequence< ::rtl::OUString > SAL_CALL OLESimpleStorage::impl_staticGetSupportedServiceNames()
84 {
85     uno::Sequence< ::rtl::OUString > aRet(1);
86     aRet[0] = ::rtl::OUString::createFromAscii("com.sun.star.embed.OLESimpleStorage");
87     return aRet;
88 }
89 
90 //-------------------------------------------------------------------------
91 ::rtl::OUString SAL_CALL OLESimpleStorage::impl_staticGetImplementationName()
92 {
93     return ::rtl::OUString::createFromAscii("com.sun.star.comp.embed.OLESimpleStorage");
94 }
95 
96 //-------------------------------------------------------------------------
97 uno::Reference< uno::XInterface > SAL_CALL OLESimpleStorage::impl_staticCreateSelfInstance(
98 			const uno::Reference< lang::XMultiServiceFactory >& xServiceManager )
99 {
100 	return uno::Reference< uno::XInterface >( *new OLESimpleStorage( xServiceManager ) );
101 }
102 
103 //-------------------------------------------------------------------------
104 void OLESimpleStorage::UpdateOriginal_Impl()
105 {
106 	if ( !m_bNoTemporaryCopy )
107 	{
108 		uno::Reference< io::XSeekable > xSeek( m_xStream, uno::UNO_QUERY_THROW );
109 		xSeek->seek( 0 );
110 
111 		uno::Reference< io::XSeekable > xTempSeek( m_xTempStream, uno::UNO_QUERY_THROW );
112 		sal_Int64 nPos = xTempSeek->getPosition();
113 		xTempSeek->seek( 0 );
114 
115 		uno::Reference< io::XInputStream > xTempInp = m_xTempStream->getInputStream();
116 		uno::Reference< io::XOutputStream > xOutputStream = m_xStream->getOutputStream();
117 		if ( !xTempInp.is() || !xOutputStream.is() )
118 			throw uno::RuntimeException();
119 
120 		uno::Reference< io::XTruncate > xTrunc( xOutputStream, uno::UNO_QUERY_THROW );
121 		xTrunc->truncate();
122 
123 		::comphelper::OStorageHelper::CopyInputToOutput( xTempInp, xOutputStream );
124 		xOutputStream->flush();
125 		xTempSeek->seek( nPos );
126 	}
127 }
128 
129 //-------------------------------------------------------------------------
130 void OLESimpleStorage::InsertInputStreamToStorage_Impl( BaseStorage* pStorage, ::rtl::OUString aName, const uno::Reference< io::XInputStream >& xInputStream )
131 	throw ( uno::Exception )
132 {
133 	if ( !pStorage || !aName.getLength() || !xInputStream.is() )
134 		throw uno::RuntimeException();
135 
136 	if ( pStorage->IsContained( aName ) )
137 		throw container::ElementExistException(); // TODO:
138 
139 	BaseStorageStream* pNewStream = pStorage->OpenStream( aName );
140 	if ( !pNewStream || pNewStream->GetError() || pStorage->GetError() )
141 	{
142 		if ( pNewStream )
143 			DELETEZ( pNewStream );
144 		pStorage->ResetError();
145 		throw io::IOException(); // TODO
146 	}
147 
148 	try
149 	{
150 		uno::Sequence< sal_Int8 > aData( nBytesCount );
151 		sal_Int32 nRead = 0;
152 		do
153 		{
154 			nRead = xInputStream->readBytes( aData, nBytesCount );
155 			if ( nRead < nBytesCount )
156 				aData.realloc( nRead );
157 
158 			sal_Int32 nWritten = pNewStream->Write( aData.getArray(), nRead );
159 			if ( nWritten < nRead )
160 				throw io::IOException();
161 		} while( nRead == nBytesCount );
162 	}
163 	catch( uno::Exception& )
164 	{
165 		DELETEZ( pNewStream );
166 		pStorage->Remove( aName );
167 
168 		throw;
169 	}
170 
171 	DELETEZ( pNewStream );
172 }
173 
174 //-------------------------------------------------------------------------
175 void OLESimpleStorage::InsertNameAccessToStorage_Impl( BaseStorage* pStorage, ::rtl::OUString aName, const uno::Reference< container::XNameAccess >& xNameAccess )
176 	throw ( uno::Exception )
177 {
178 	if ( !pStorage || !aName.getLength() || !xNameAccess.is() )
179 		throw uno::RuntimeException();
180 
181 	if ( pStorage->IsContained( aName ) )
182 		throw container::ElementExistException(); // TODO:
183 
184 	BaseStorage* pNewStorage = pStorage->OpenStorage( aName );
185 	if ( !pNewStorage || pNewStorage->GetError() || pStorage->GetError() )
186 	{
187 		if ( pNewStorage )
188 			DELETEZ( pNewStorage );
189 		pStorage->ResetError();
190 		throw io::IOException(); // TODO
191 	}
192 
193 	try
194 	{
195 		uno::Sequence< ::rtl::OUString > aElements = xNameAccess->getElementNames();
196 		for ( sal_Int32 nInd = 0; nInd < aElements.getLength(); nInd++ )
197 		{
198 			uno::Reference< io::XInputStream > xInputStream;
199 			uno::Reference< container::XNameAccess > xSubNameAccess;
200 			uno::Any aAny = xNameAccess->getByName( aElements[nInd] );
201 			if ( aAny >>= xInputStream )
202 				InsertInputStreamToStorage_Impl( pNewStorage, aElements[nInd], xInputStream );
203 			else if ( aAny >>= xSubNameAccess )
204 				InsertNameAccessToStorage_Impl( pNewStorage, aElements[nInd], xSubNameAccess );
205 		}
206 	}
207 	catch( uno::Exception& )
208 	{
209 		DELETEZ( pNewStorage );
210 		pStorage->Remove( aName );
211 
212 		throw;
213 	}
214 
215 	DELETEZ( pNewStorage );
216 }
217 
218 //____________________________________________________________________________________________________
219 //	XInitialization
220 //____________________________________________________________________________________________________
221 
222 void SAL_CALL OLESimpleStorage::initialize( const uno::Sequence< uno::Any >& aArguments )
223 		throw ( uno::Exception,
224 				uno::RuntimeException)
225 {
226 	if ( m_pStream || m_pStorage )
227 		throw io::IOException(); // TODO: already initilized
228 
229 	sal_Int32 nArgNum = aArguments.getLength();
230 	OSL_ENSURE( nArgNum >= 1 && nArgNum <= 2, "Wrong parameter number" );
231 
232 	if ( nArgNum < 1 || nArgNum > 2 )
233 		throw lang::IllegalArgumentException(); // TODO:
234 
235 	uno::Reference< io::XStream > xStream;
236 	uno::Reference< io::XInputStream > xInputStream;
237 	if ( !( aArguments[0] >>= xStream ) && !( aArguments[0] >>= xInputStream ) )
238 		throw lang::IllegalArgumentException(); // TODO:
239 
240 	if ( nArgNum == 2 )
241 	{
242 		if ( !( aArguments[1] >>= m_bNoTemporaryCopy ) )
243 			throw lang::IllegalArgumentException(); // TODO:
244 	}
245 
246 	if ( m_bNoTemporaryCopy )
247 	{
248 		// TODO: ???
249 		// If the temporary stream is not created, the original stream must be wrapped
250 		// since SvStream wrapper closes the stream is owns
251 		if ( xInputStream.is() )
252 		{
253 			// the stream must be seekable for direct access
254 			uno::Reference< io::XSeekable > xSeek( xInputStream, uno::UNO_QUERY_THROW );
255 			m_pStream = ::utl::UcbStreamHelper::CreateStream( xInputStream, sal_False );
256 		}
257 		else if ( xStream.is() )
258 		{
259 			// the stream must be seekable for direct access
260 			uno::Reference< io::XSeekable > xSeek( xStream, uno::UNO_QUERY_THROW );
261 			m_pStream = ::utl::UcbStreamHelper::CreateStream( xStream, sal_False );
262 		}
263 		else
264 			throw lang::IllegalArgumentException(); // TODO:
265 	}
266 	else
267 	{
268 		uno::Reference < io::XStream > xTempFile(
269 				m_xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ),
270 				uno::UNO_QUERY_THROW );
271 		uno::Reference < io::XSeekable > xTempSeek( xTempFile, uno::UNO_QUERY_THROW );
272 		uno::Reference< io::XOutputStream > xTempOut = xTempFile->getOutputStream();
273 		if ( !xTempOut.is() )
274 			throw uno::RuntimeException();
275 
276 		if ( xInputStream.is() )
277 		{
278 			try
279 			{
280 				uno::Reference< io::XSeekable > xSeek( xInputStream, uno::UNO_QUERY_THROW );
281 				xSeek->seek( 0 );
282 			}
283 			catch( uno::Exception& )
284 			{}
285 
286 			::comphelper::OStorageHelper::CopyInputToOutput( xInputStream, xTempOut );
287 			xTempOut->closeOutput();
288 			xTempSeek->seek( 0 );
289 			uno::Reference< io::XInputStream > xTempInput = xTempFile->getInputStream();
290 			m_pStream = ::utl::UcbStreamHelper::CreateStream( xTempInput, sal_False );
291 		}
292 		else if ( xStream.is() )
293 		{
294 			// not sure that the storage flashes the stream on commit
295 			m_xStream = xStream;
296 			m_xTempStream = xTempFile;
297 
298 			uno::Reference< io::XSeekable > xSeek( xStream, uno::UNO_QUERY_THROW );
299 			xSeek->seek( 0 );
300 			uno::Reference< io::XInputStream > xInpStream = xStream->getInputStream();
301 			if ( !xInpStream.is() || !xStream->getOutputStream().is() )
302 				throw uno::RuntimeException();
303 
304 			::comphelper::OStorageHelper::CopyInputToOutput( xInpStream, xTempOut );
305 			xTempOut->flush();
306 			xTempSeek->seek( 0 );
307 
308 			m_pStream = ::utl::UcbStreamHelper::CreateStream( xTempFile, sal_False );
309 		}
310 		else
311 			throw lang::IllegalArgumentException(); // TODO:
312 	}
313 
314 	if ( !m_pStream || m_pStream->GetError() )
315 		throw io::IOException(); // TODO
316 
317 	m_pStorage = new Storage( *m_pStream, sal_False );
318 }
319 
320 
321 //____________________________________________________________________________________________________
322 //	XNameContainer
323 //____________________________________________________________________________________________________
324 
325 // --------------------------------------------------------------------------------
326 void SAL_CALL OLESimpleStorage::insertByName( const ::rtl::OUString& aName, const uno::Any& aElement )
327 		throw ( lang::IllegalArgumentException,
328 				container::ElementExistException,
329 				lang::WrappedTargetException,
330 				uno::RuntimeException)
331 {
332 	::osl::MutexGuard aGuard( m_aMutex );
333 
334 	if ( m_bDisposed )
335 		throw lang::DisposedException();
336 
337 	  if ( !m_pStorage )
338 		throw uno::RuntimeException();
339 
340 	uno::Reference< io::XStream > xStream;
341 	uno::Reference< io::XInputStream > xInputStream;
342 	uno::Reference< container::XNameAccess > xNameAccess;
343 
344 	try
345 	{
346 		if ( !m_bNoTemporaryCopy && !m_xStream.is() )
347 			throw io::IOException(); // TODO
348 
349 		if ( aElement >>= xStream )
350 			xInputStream = xStream->getInputStream();
351 		else if ( !( aElement >>= xInputStream ) && !( aElement >>= xNameAccess ) )
352 			throw lang::IllegalArgumentException(); // TODO:
353 
354 		if ( xInputStream.is() )
355 			InsertInputStreamToStorage_Impl( m_pStorage, aName, xInputStream );
356 		else if ( xNameAccess.is() )
357 			InsertNameAccessToStorage_Impl( m_pStorage, aName, xNameAccess );
358 		else
359 			throw uno::RuntimeException();
360 	}
361 	catch( uno::RuntimeException& )
362 	{
363 		throw;
364 	}
365 	catch( container::ElementExistException& )
366 	{
367 		throw;
368 	}
369 	catch( uno::Exception& e )
370 	{
371 		throw lang::WrappedTargetException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Insert has failed!" ) ),
372 											uno::Reference< uno::XInterface >(),
373 											uno::makeAny( e ) );
374 	}
375 }
376 
377 // --------------------------------------------------------------------------------
378 void SAL_CALL OLESimpleStorage::removeByName( const ::rtl::OUString& aName )
379 		throw ( container::NoSuchElementException,
380 				lang::WrappedTargetException,
381 				uno::RuntimeException)
382 {
383 	::osl::MutexGuard aGuard( m_aMutex );
384 
385 	if ( m_bDisposed )
386 		throw lang::DisposedException();
387 
388 	  if ( !m_pStorage )
389 		throw uno::RuntimeException();
390 
391 	if ( !m_bNoTemporaryCopy && !m_xStream.is() )
392 		throw lang::WrappedTargetException(); // io::IOException(); // TODO
393 
394 	if ( !m_pStorage->IsContained( aName ) )
395 		throw container::NoSuchElementException(); // TODO:
396 
397 	m_pStorage->Remove( aName );
398 
399 	if ( m_pStorage->GetError() )
400 	{
401 		m_pStorage->ResetError();
402 		throw lang::WrappedTargetException(); // io::IOException(); // TODO
403 	}
404 }
405 
406 // --------------------------------------------------------------------------------
407 void SAL_CALL OLESimpleStorage::replaceByName( const ::rtl::OUString& aName, const uno::Any& aElement )
408 		throw ( lang::IllegalArgumentException,
409 				container::NoSuchElementException,
410 				lang::WrappedTargetException,
411 				uno::RuntimeException)
412 {
413 	::osl::MutexGuard aGuard( m_aMutex );
414 
415 	if ( m_bDisposed )
416 		throw lang::DisposedException();
417 
418 	removeByName( aName );
419 
420 	try
421 	{
422 		insertByName( aName, aElement );
423 	}
424 	catch( container::ElementExistException& )
425 	{
426 	   	uno::Any aCaught( ::cppu::getCaughtException() );
427 
428 		throw lang::WrappedTargetException( ::rtl::OUString::createFromAscii( "Can't copy raw stream" ),
429 											uno::Reference< uno::XInterface >(),
430 											aCaught );
431 	}
432 }
433 
434 // --------------------------------------------------------------------------------
435 uno::Any SAL_CALL OLESimpleStorage::getByName( const ::rtl::OUString& aName )
436 		throw ( container::NoSuchElementException,
437 				lang::WrappedTargetException,
438 				uno::RuntimeException )
439 {
440 	::osl::MutexGuard aGuard( m_aMutex );
441 
442 	if ( m_bDisposed )
443 		throw lang::DisposedException();
444 
445 	  if ( !m_pStorage )
446 		throw uno::RuntimeException();
447 
448 	if ( !m_pStorage->IsContained( aName ) )
449 		throw container::NoSuchElementException(); // TODO:
450 
451 	uno::Any aResult;
452 
453 	uno::Reference< io::XStream > xTempFile(
454 		m_xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ),
455 		uno::UNO_QUERY );
456 	uno::Reference< io::XSeekable > xSeekable( xTempFile, uno::UNO_QUERY_THROW );
457 	uno::Reference< io::XOutputStream > xOutputStream = xTempFile->getOutputStream();
458 	uno::Reference< io::XInputStream > xInputStream = xTempFile->getInputStream();
459 	if ( !xOutputStream.is() || !xInputStream.is() )
460 		throw uno::RuntimeException();
461 
462 	if ( m_pStorage->IsStorage( aName ) )
463 	{
464 		BaseStorage* pStrg = m_pStorage->OpenStorage( aName );
465 		m_pStorage->ResetError();
466 		if ( !pStrg )
467 			throw io::IOException();
468 
469 		SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( xTempFile, sal_False ); // do not close the original stream
470 		if ( !pStream )
471 			throw uno::RuntimeException();
472 
473 		BaseStorage* pNewStor = new Storage( *pStream, sal_False );
474 		sal_Bool bSuccess =
475 			( pStrg->CopyTo( pNewStor ) && pNewStor->Commit() && !pNewStor->GetError() && !pStrg->GetError() );
476 
477 		DELETEZ( pNewStor );
478 		DELETEZ( pStrg );
479 		DELETEZ( pStream );
480 
481 		if ( !bSuccess )
482 			throw uno::RuntimeException();
483 
484 		uno::Sequence< uno::Any > aArgs( 2 );
485 		aArgs[0] <<= xInputStream; // allow readonly access only
486 		aArgs[1] <<= (sal_Bool)sal_True; // do not create copy
487 
488 		uno::Reference< container::XNameContainer > xResultNameContainer(
489 			m_xFactory->createInstanceWithArguments(
490 					::rtl::OUString::createFromAscii( "com.sun.star.embed.OLESimpleStorage" ),
491 					aArgs ),
492 			uno::UNO_QUERY_THROW );
493 
494 		aResult <<= xResultNameContainer;
495 	}
496 	else
497 	{
498 		BaseStorageStream* pStream = m_pStorage->OpenStream( aName, STREAM_READ | STREAM_SHARE_DENYALL | STREAM_NOCREATE );
499 		if ( !pStream || pStream->GetError() || m_pStorage->GetError() )
500 		{
501 			m_pStorage->ResetError();
502 			DELETEZ( pStream );
503 			throw io::IOException(); // TODO
504 		}
505 
506 		try
507 		{
508 			uno::Sequence< sal_Int8 > aData( nBytesCount );
509 			sal_Int32 nSize = nBytesCount;
510 			sal_Int32 nRead = 0;
511 			while( 0 != ( nRead = pStream->Read( aData.getArray(), nSize ) ) )
512 			{
513 				if ( nRead < nSize )
514 				{
515 					nSize = nRead;
516 					aData.realloc( nSize );
517 				}
518 
519 				xOutputStream->writeBytes( aData );
520 			}
521 
522 			if ( pStream->GetError() )
523 				throw io::IOException(); // TODO
524 
525 			xOutputStream->closeOutput();
526 			xSeekable->seek( 0 );
527 		}
528 		catch( uno::RuntimeException& )
529 		{
530 			DELETEZ( pStream );
531 			throw;
532 		}
533 		catch( uno::Exception& )
534 		{
535 			DELETEZ( pStream );
536 			throw lang::WrappedTargetException(); // TODO:
537 		}
538 
539 		DELETEZ( pStream );
540 
541 		aResult <<= xInputStream;
542 	}
543 
544 	return aResult;
545 }
546 
547 // --------------------------------------------------------------------------------
548 uno::Sequence< ::rtl::OUString > SAL_CALL OLESimpleStorage::getElementNames()
549 		throw ( uno::RuntimeException )
550 {
551 	::osl::MutexGuard aGuard( m_aMutex );
552 
553 	if ( m_bDisposed )
554 		throw lang::DisposedException();
555 
556 	  if ( !m_pStorage )
557 		throw uno::RuntimeException();
558 
559 	SvStorageInfoList aList;
560 	m_pStorage->FillInfoList( &aList );
561 
562 	if ( m_pStorage->GetError() )
563 	{
564 		m_pStorage->ResetError();
565 		throw uno::RuntimeException(); // TODO:
566 	}
567 
568 	uno::Sequence< ::rtl::OUString > aSeq( aList.Count() );
569 	for ( sal_uInt32 nInd = 0; nInd < aList.Count(); nInd++ )
570 		aSeq[nInd] = aList[nInd].GetName();
571 
572 	return aSeq;
573 }
574 
575 // --------------------------------------------------------------------------------
576 sal_Bool SAL_CALL OLESimpleStorage::hasByName( const ::rtl::OUString& aName )
577 		throw ( uno::RuntimeException )
578 {
579 	::osl::MutexGuard aGuard( m_aMutex );
580 
581 	if ( m_bDisposed )
582 		throw lang::DisposedException();
583 
584 	 if ( !m_pStorage )
585 		throw uno::RuntimeException();
586 
587 	sal_Bool bResult = m_pStorage->IsContained( aName );
588 
589 	if ( m_pStorage->GetError() )
590 	{
591 		m_pStorage->ResetError();
592 		throw uno::RuntimeException(); // TODO:
593 	}
594 
595 	return bResult;
596 }
597 
598 // --------------------------------------------------------------------------------
599 uno::Type SAL_CALL OLESimpleStorage::getElementType()
600 		throw ( uno::RuntimeException )
601 {
602 	::osl::MutexGuard aGuard( m_aMutex );
603 
604 	if ( m_bDisposed )
605 		throw lang::DisposedException();
606 
607 	return getCppuType( (const uno::Reference< io::XInputStream >*)NULL );
608 }
609 
610 // --------------------------------------------------------------------------------
611 sal_Bool SAL_CALL OLESimpleStorage::hasElements()
612 		throw ( uno::RuntimeException )
613 {
614 	::osl::MutexGuard aGuard( m_aMutex );
615 
616 	if ( m_bDisposed )
617 		throw lang::DisposedException();
618 
619 	  if ( !m_pStorage )
620 		throw uno::RuntimeException();
621 
622 	SvStorageInfoList aList;
623 	m_pStorage->FillInfoList( &aList );
624 
625 	if ( m_pStorage->GetError() )
626 	{
627 		m_pStorage->ResetError();
628 		throw uno::RuntimeException(); // TODO:
629 	}
630 
631 	return ( aList.Count() != 0 );
632 }
633 
634 //____________________________________________________________________________________________________
635 //	XComponent
636 //____________________________________________________________________________________________________
637 
638 // --------------------------------------------------------------------------------
639 void SAL_CALL OLESimpleStorage::dispose()
640 		throw ( uno::RuntimeException )
641 {
642 	::osl::MutexGuard aGuard( m_aMutex );
643 
644 	if ( m_bDisposed )
645 		throw lang::DisposedException();
646 
647 	if ( m_pListenersContainer )
648 	{
649    		lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >(this) );
650 		m_pListenersContainer->disposeAndClear( aSource );
651 	}
652 
653 	DELETEZ( m_pStorage );
654 	DELETEZ( m_pStream );
655 
656 	m_xStream = uno::Reference< io::XStream >();
657 	m_xTempStream = uno::Reference< io::XStream >();
658 
659 	m_bDisposed = sal_True;
660 }
661 
662 // --------------------------------------------------------------------------------
663 void SAL_CALL OLESimpleStorage::addEventListener(
664 			const uno::Reference< lang::XEventListener >& xListener )
665 		throw ( uno::RuntimeException )
666 {
667 	::osl::MutexGuard aGuard( m_aMutex );
668 
669 	if ( m_bDisposed )
670 		throw lang::DisposedException();
671 
672 	if ( !m_pListenersContainer )
673 		m_pListenersContainer = new ::cppu::OInterfaceContainerHelper( m_aMutex );
674 
675 	m_pListenersContainer->addInterface( xListener );
676 }
677 
678 // --------------------------------------------------------------------------------
679 void SAL_CALL OLESimpleStorage::removeEventListener(
680 			const uno::Reference< lang::XEventListener >& xListener )
681 		throw ( uno::RuntimeException )
682 {
683 	::osl::MutexGuard aGuard( m_aMutex );
684 
685 	if ( m_bDisposed )
686 		throw lang::DisposedException();
687 
688 	if ( m_pListenersContainer )
689 		m_pListenersContainer->removeInterface( xListener );
690 }
691 
692 //____________________________________________________________________________________________________
693 //	XTransactedObject
694 //____________________________________________________________________________________________________
695 
696 // --------------------------------------------------------------------------------
697 void SAL_CALL OLESimpleStorage::commit()
698 		throw ( ::com::sun::star::io::IOException,
699 				::com::sun::star::lang::WrappedTargetException,
700 				::com::sun::star::uno::RuntimeException )
701 {
702 	::osl::MutexGuard aGuard( m_aMutex );
703 
704 	if ( m_bDisposed )
705 		throw lang::DisposedException();
706 
707 	 if ( !m_pStorage )
708 		throw uno::RuntimeException();
709 
710 	if ( !m_bNoTemporaryCopy && !m_xStream.is() )
711 		throw io::IOException(); // TODO
712 
713 	if ( !m_pStorage->Commit() || m_pStorage->GetError() )
714 	{
715 		m_pStorage->ResetError();
716 		throw io::IOException(); // TODO
717 	}
718 
719 	UpdateOriginal_Impl();
720 }
721 
722 // --------------------------------------------------------------------------------
723 void SAL_CALL OLESimpleStorage::revert()
724 		throw ( ::com::sun::star::io::IOException,
725 				::com::sun::star::lang::WrappedTargetException,
726 				::com::sun::star::uno::RuntimeException )
727 {
728 	::osl::MutexGuard aGuard( m_aMutex );
729 
730 	if ( m_bDisposed )
731 		throw lang::DisposedException();
732 
733 	 if ( !m_pStorage )
734 		throw uno::RuntimeException();
735 
736 	if ( !m_bNoTemporaryCopy && !m_xStream.is() )
737 		throw io::IOException(); // TODO
738 
739 	if ( !m_pStorage->Revert() || m_pStorage->GetError() )
740 	{
741 		m_pStorage->ResetError();
742 		throw io::IOException(); // TODO
743 	}
744 
745 	UpdateOriginal_Impl();
746 }
747 
748 //____________________________________________________________________________________________________
749 //	XClassifiedObject
750 //____________________________________________________________________________________________________
751 
752 uno::Sequence< sal_Int8 > SAL_CALL OLESimpleStorage::getClassID()
753 	throw ( uno::RuntimeException )
754 {
755 	::osl::MutexGuard aGuard( m_aMutex );
756 
757 	if ( m_bDisposed )
758 		throw lang::DisposedException();
759 
760 	if ( !m_pStorage )
761 		throw uno::RuntimeException();
762 
763 	return m_pStorage->GetClassName().GetByteSequence();
764 }
765 
766 ::rtl::OUString SAL_CALL OLESimpleStorage::getClassName()
767 	throw ( uno::RuntimeException )
768 {
769 	return ::rtl::OUString();
770 }
771 
772 void SAL_CALL OLESimpleStorage::setClassInfo( const uno::Sequence< sal_Int8 >& /*aClassID*/,
773 							const ::rtl::OUString& /*sClassName*/ )
774 		throw ( lang::NoSupportException,
775 				uno::RuntimeException )
776 {
777 	throw lang::NoSupportException();
778 }
779 
780 //____________________________________________________________________________________________________
781 //	XServiceInfo
782 //____________________________________________________________________________________________________
783 
784 // --------------------------------------------------------------------------------
785 ::rtl::OUString SAL_CALL OLESimpleStorage::getImplementationName()
786 		throw ( uno::RuntimeException )
787 {
788 	return impl_staticGetImplementationName();
789 }
790 
791 // --------------------------------------------------------------------------------
792 ::sal_Bool SAL_CALL OLESimpleStorage::supportsService( const ::rtl::OUString& ServiceName )
793 		throw ( uno::RuntimeException )
794 {
795 	uno::Sequence< ::rtl::OUString > aSeq = impl_staticGetSupportedServiceNames();
796 
797 	for ( sal_Int32 nInd = 0; nInd < aSeq.getLength(); nInd++ )
798     	if ( ServiceName.compareTo( aSeq[nInd] ) == 0 )
799         	return sal_True;
800 
801 	return sal_False;
802 }
803 
804 // --------------------------------------------------------------------------------
805 uno::Sequence< ::rtl::OUString > SAL_CALL OLESimpleStorage::getSupportedServiceNames()
806 		throw ( uno::RuntimeException )
807 {
808 	return impl_staticGetSupportedServiceNames();
809 }
810 
811 
812