tdf#162786, tdf#161947: Add support for setuptools and pip
[LibreOffice.git] / sot / source / unoolestorage / xolesimplestorage.cxx
bloba3ce980fdbe48a842f076b884576bf16ad6a6a46
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "xolesimplestorage.hxx"
22 #include <com/sun/star/embed/OLESimpleStorage.hpp>
23 #include <com/sun/star/lang/DisposedException.hpp>
24 #include <com/sun/star/lang/NoSupportException.hpp>
25 #include <com/sun/star/io/IOException.hpp>
26 #include <com/sun/star/io/XStream.hpp>
27 #include <com/sun/star/io/XInputStream.hpp>
28 #include <com/sun/star/io/XSeekable.hpp>
29 #include <com/sun/star/io/XTruncate.hpp>
30 #include <com/sun/star/io/TempFile.hpp>
32 #include <comphelper/storagehelper.hxx>
33 #include <unotools/ucbstreamhelper.hxx>
34 #include <cppuhelper/exc_hlp.hxx>
35 #include <cppuhelper/supportsservice.hxx>
36 #include <sot/stg.hxx>
37 #include <sot/storinfo.hxx>
38 #include <utility>
40 using namespace ::com::sun::star;
42 const sal_Int32 nBytesCount = 32000;
45 OLESimpleStorage::OLESimpleStorage(
46 css::uno::Reference<css::uno::XComponentContext> xContext,
47 css::uno::Sequence<css::uno::Any> const &aArguments)
48 : m_bDisposed( false )
49 , m_xContext(std::move( xContext ))
50 , m_bNoTemporaryCopy( false )
52 sal_Int32 nArgNum = aArguments.getLength();
53 if ( nArgNum < 1 || nArgNum > 2 )
54 throw lang::IllegalArgumentException(); // TODO:
56 uno::Reference< io::XStream > xStream;
57 uno::Reference< io::XInputStream > xInputStream;
58 if ( !( aArguments[0] >>= xStream ) && !( aArguments[0] >>= xInputStream ) )
59 throw lang::IllegalArgumentException(); // TODO:
61 if ( nArgNum == 2 )
63 if ( !( aArguments[1] >>= m_bNoTemporaryCopy ) )
64 throw lang::IllegalArgumentException(); // TODO:
67 if ( m_bNoTemporaryCopy )
69 // TODO: ???
70 // If the temporary stream is not created, the original stream must be wrapped
71 // since SvStream wrapper closes the stream is owns
72 if ( xInputStream.is() )
74 // the stream must be seekable for direct access
75 uno::Reference< io::XSeekable > xSeek( xInputStream, uno::UNO_QUERY_THROW );
76 m_pStream = ::utl::UcbStreamHelper::CreateStream( xInputStream, false );
78 else if ( xStream.is() )
80 // the stream must be seekable for direct access
81 uno::Reference< io::XSeekable > xSeek( xStream, uno::UNO_QUERY_THROW );
82 m_pStream = ::utl::UcbStreamHelper::CreateStream( xStream, false );
84 else
85 throw lang::IllegalArgumentException(); // TODO:
87 else
89 uno::Reference < io::XStream > xTempFile( io::TempFile::create(m_xContext),
90 uno::UNO_QUERY_THROW );
91 uno::Reference < io::XSeekable > xTempSeek( xTempFile, uno::UNO_QUERY_THROW );
92 uno::Reference< io::XOutputStream > xTempOut = xTempFile->getOutputStream();
93 if ( !xTempOut.is() )
94 throw uno::RuntimeException();
96 if ( xInputStream.is() )
98 try
100 uno::Reference< io::XSeekable > xSeek( xInputStream, uno::UNO_QUERY );
101 if (xSeek)
102 xSeek->seek( 0 );
104 catch( uno::Exception& )
107 ::comphelper::OStorageHelper::CopyInputToOutput( xInputStream, xTempOut );
108 xTempOut->closeOutput();
109 xTempSeek->seek( 0 );
110 uno::Reference< io::XInputStream > xTempInput = xTempFile->getInputStream();
111 m_pStream = ::utl::UcbStreamHelper::CreateStream( xTempInput, false );
113 else if ( xStream.is() )
115 // not sure that the storage flashes the stream on commit
116 m_xStream = xStream;
117 m_xTempStream = xTempFile;
119 uno::Reference< io::XSeekable > xSeek( xStream, uno::UNO_QUERY_THROW );
120 xSeek->seek( 0 );
121 uno::Reference< io::XInputStream > xInpStream = xStream->getInputStream();
122 if ( !xInpStream.is() || !xStream->getOutputStream().is() )
123 throw uno::RuntimeException();
125 ::comphelper::OStorageHelper::CopyInputToOutput( xInpStream, xTempOut );
126 xTempOut->flush();
127 xTempSeek->seek( 0 );
129 m_pStream = ::utl::UcbStreamHelper::CreateStream( xTempFile, false );
131 else
132 throw lang::IllegalArgumentException(); // TODO:
135 if ( !m_pStream || m_pStream->GetError() )
136 throw io::IOException(); // TODO
138 m_pStorage.reset(new Storage( *m_pStream, false ));
141 OLESimpleStorage::~OLESimpleStorage()
143 try {
144 osl_atomic_increment(&m_refCount);
145 dispose();
146 } catch( uno::Exception& )
150 void OLESimpleStorage::UpdateOriginal_Impl()
152 if ( m_bNoTemporaryCopy )
153 return;
155 uno::Reference< io::XSeekable > xSeek( m_xStream, uno::UNO_QUERY_THROW );
156 xSeek->seek( 0 );
158 uno::Reference< io::XSeekable > xTempSeek( m_xTempStream, uno::UNO_QUERY_THROW );
159 sal_Int64 nPos = xTempSeek->getPosition();
160 xTempSeek->seek( 0 );
162 uno::Reference< io::XInputStream > xTempInp = m_xTempStream->getInputStream();
163 uno::Reference< io::XOutputStream > xOutputStream = m_xStream->getOutputStream();
164 if ( !xTempInp.is() || !xOutputStream.is() )
165 throw uno::RuntimeException();
167 uno::Reference< io::XTruncate > xTrunc( xOutputStream, uno::UNO_QUERY_THROW );
168 xTrunc->truncate();
170 ::comphelper::OStorageHelper::CopyInputToOutput( xTempInp, xOutputStream );
171 xOutputStream->flush();
172 xTempSeek->seek( nPos );
176 void OLESimpleStorage::InsertInputStreamToStorage_Impl( BaseStorage* pStorage, const OUString & aName, const uno::Reference< io::XInputStream >& xInputStream )
178 if ( !pStorage || aName.isEmpty() || !xInputStream.is() )
179 throw uno::RuntimeException();
181 if ( pStorage->IsContained( aName ) )
182 throw container::ElementExistException(); // TODO:
184 std::unique_ptr<BaseStorageStream> pNewStream(pStorage->OpenStream( aName ));
185 if ( !pNewStream || pNewStream->GetError() || pStorage->GetError() )
187 pNewStream.reset();
188 pStorage->ResetError();
189 throw io::IOException(); // TODO
194 uno::Sequence< sal_Int8 > aData( nBytesCount );
195 sal_Int32 nRead = 0;
198 nRead = xInputStream->readBytes( aData, nBytesCount );
200 sal_Int32 nWritten = pNewStream->Write( aData.getConstArray(), nRead );
201 if ( nWritten < nRead )
202 throw io::IOException();
203 } while( nRead == nBytesCount );
205 catch( uno::Exception& )
207 pNewStream.reset();
208 pStorage->Remove( aName );
210 throw;
215 void OLESimpleStorage::InsertNameAccessToStorage_Impl( BaseStorage* pStorage, const OUString & aName, const uno::Reference< container::XNameAccess >& xNameAccess )
217 if ( !pStorage || aName.isEmpty() || !xNameAccess.is() )
218 throw uno::RuntimeException();
220 if ( pStorage->IsContained( aName ) )
221 throw container::ElementExistException(); // TODO:
223 std::unique_ptr<BaseStorage> pNewStorage(pStorage->OpenStorage( aName ));
224 if ( !pNewStorage || pNewStorage->GetError() || pStorage->GetError() )
226 pNewStorage.reset();
227 pStorage->ResetError();
228 throw io::IOException(); // TODO
233 const uno::Sequence< OUString > aElements = xNameAccess->getElementNames();
234 for ( const auto& rElement : aElements )
236 uno::Reference< io::XInputStream > xInputStream;
237 uno::Reference< container::XNameAccess > xSubNameAccess;
238 uno::Any aAny = xNameAccess->getByName( rElement );
239 if ( aAny >>= xInputStream )
240 InsertInputStreamToStorage_Impl( pNewStorage.get(), rElement, xInputStream );
241 else if ( aAny >>= xSubNameAccess )
242 InsertNameAccessToStorage_Impl( pNewStorage.get(), rElement, xSubNameAccess );
245 catch( uno::Exception& )
247 pNewStorage.reset();
248 pStorage->Remove( aName );
250 throw;
255 // XNameContainer
258 void SAL_CALL OLESimpleStorage::insertByName( const OUString& aName, const uno::Any& aElement )
260 std::unique_lock aGuard( m_aMutex );
262 if ( m_bDisposed )
263 throw lang::DisposedException();
265 if ( !m_pStorage )
266 throw uno::RuntimeException();
268 uno::Reference< io::XStream > xStream;
269 uno::Reference< io::XInputStream > xInputStream;
270 uno::Reference< container::XNameAccess > xNameAccess;
274 if ( !m_bNoTemporaryCopy && !m_xStream.is() )
275 throw io::IOException(); // TODO
277 if ( aElement >>= xStream )
278 xInputStream = xStream->getInputStream();
279 else if ( !( aElement >>= xInputStream ) && !( aElement >>= xNameAccess ) )
280 throw lang::IllegalArgumentException(); // TODO:
282 if ( xInputStream.is() )
283 InsertInputStreamToStorage_Impl( m_pStorage.get(), aName, xInputStream );
284 else if ( xNameAccess.is() )
285 InsertNameAccessToStorage_Impl( m_pStorage.get(), aName, xNameAccess );
286 else
287 throw uno::RuntimeException();
289 catch( uno::RuntimeException& )
291 throw;
293 catch( container::ElementExistException& )
295 throw;
297 catch( const uno::Exception& )
299 css::uno::Any anyEx = cppu::getCaughtException();
300 throw lang::WrappedTargetException(u"Insert has failed!"_ustr,
301 uno::Reference< uno::XInterface >(),
302 anyEx );
307 void SAL_CALL OLESimpleStorage::removeByName( const OUString& aName )
309 std::unique_lock aGuard( m_aMutex );
311 if ( m_bDisposed )
312 throw lang::DisposedException();
314 if ( !m_pStorage )
315 throw uno::RuntimeException();
317 if ( !m_bNoTemporaryCopy && !m_xStream.is() )
318 throw lang::WrappedTargetException(); // io::IOException(); // TODO
320 if ( !m_pStorage->IsContained( aName ) )
321 throw container::NoSuchElementException(); // TODO:
323 m_pStorage->Remove( aName );
325 if ( m_pStorage->GetError() )
327 m_pStorage->ResetError();
328 throw lang::WrappedTargetException(); // io::IOException(); // TODO
333 void SAL_CALL OLESimpleStorage::replaceByName( const OUString& aName, const uno::Any& aElement )
335 std::unique_lock aGuard( m_aMutex );
337 if ( m_bDisposed )
338 throw lang::DisposedException();
340 removeByName( aName );
344 insertByName( aName, aElement );
346 catch( container::ElementExistException& )
348 uno::Any aCaught( ::cppu::getCaughtException() );
350 throw lang::WrappedTargetException(u"Can't copy raw stream"_ustr,
351 uno::Reference< uno::XInterface >(),
352 aCaught );
357 uno::Any SAL_CALL OLESimpleStorage::getByName( const OUString& aName )
359 std::unique_lock aGuard( m_aMutex );
361 if ( m_bDisposed )
362 throw lang::DisposedException();
364 if ( !m_pStorage )
365 throw uno::RuntimeException();
367 if ( !m_pStorage->IsContained( aName ) )
368 throw container::NoSuchElementException(); // TODO:
370 uno::Any aResult;
372 uno::Reference< io::XStream > xTempFile = io::TempFile::create(m_xContext);
373 uno::Reference< io::XSeekable > xSeekable( xTempFile, uno::UNO_QUERY_THROW );
374 uno::Reference< io::XOutputStream > xOutputStream = xTempFile->getOutputStream();
375 uno::Reference< io::XInputStream > xInputStream = xTempFile->getInputStream();
376 if ( !xOutputStream.is() || !xInputStream.is() )
377 throw uno::RuntimeException();
379 if ( m_pStorage->IsStorage( aName ) )
381 std::unique_ptr<BaseStorage> pStrg(m_pStorage->OpenStorage( aName ));
382 m_pStorage->ResetError();
383 if ( !pStrg )
384 throw lang::WrappedTargetException(); // io::IOException(); // TODO
386 std::unique_ptr<SvStream> pStream = ::utl::UcbStreamHelper::CreateStream( xTempFile, false ); // do not close the original stream
387 if ( !pStream )
388 throw uno::RuntimeException();
390 std::unique_ptr<BaseStorage> pNewStor(new Storage( *pStream, false ));
391 bool bSuccess = ( pStrg->CopyTo( *pNewStor ) && pNewStor->Commit() &&
392 !pNewStor->GetError() && !pStrg->GetError() );
394 pNewStor.reset();
395 pStrg.reset();
396 pStream.reset();
398 if ( !bSuccess )
399 throw uno::RuntimeException();
401 uno::Reference< container::XNameContainer > xResultNameContainer(
402 css::embed::OLESimpleStorage::createFromInputStream(m_xContext, xInputStream, true),
403 uno::UNO_QUERY_THROW );
405 aResult <<= xResultNameContainer;
407 else
409 std::unique_ptr<BaseStorageStream> pStream(m_pStorage->OpenStream( aName, StreamMode::READ | StreamMode::SHARE_DENYALL | StreamMode::NOCREATE ));
412 if ( !pStream || pStream->GetError() || m_pStorage->GetError() )
414 m_pStorage->ResetError();
415 throw io::IOException(); // TODO
418 uno::Sequence< sal_Int8 > aData( nBytesCount );
419 sal_Int32 nSize = nBytesCount;
420 sal_Int32 nRead = 0;
421 while( 0 != ( nRead = pStream->Read( aData.getArray(), nSize ) ) )
423 if ( nRead < nSize )
425 nSize = nRead;
426 aData.realloc( nSize );
429 xOutputStream->writeBytes( aData );
432 if ( pStream->GetError() )
433 throw io::IOException(); // TODO
435 xOutputStream->closeOutput();
436 xSeekable->seek( 0 );
438 catch (const uno::RuntimeException&)
440 throw;
442 catch (const uno::Exception& ex)
444 css::uno::Any anyEx = cppu::getCaughtException();
445 throw css::lang::WrappedTargetException( ex.Message,
446 nullptr, anyEx );
449 pStream.reset();
451 aResult <<= xInputStream;
454 return aResult;
458 uno::Sequence< OUString > SAL_CALL OLESimpleStorage::getElementNames()
460 std::unique_lock aGuard( m_aMutex );
462 if ( m_bDisposed )
463 throw lang::DisposedException();
465 if ( !m_pStorage )
466 throw uno::RuntimeException();
468 SvStorageInfoList aList;
469 m_pStorage->FillInfoList( &aList );
471 if ( m_pStorage->GetError() )
473 m_pStorage->ResetError();
474 throw uno::RuntimeException(); // TODO:
477 uno::Sequence< OUString > aSeq( aList.size() );
478 auto aSeqRange = asNonConstRange(aSeq);
479 for ( size_t nInd = 0; nInd < aList.size(); nInd++ )
480 aSeqRange[nInd] = aList[nInd].GetName();
482 return aSeq;
486 sal_Bool SAL_CALL OLESimpleStorage::hasByName( const OUString& aName )
488 std::unique_lock aGuard( m_aMutex );
490 if ( m_bDisposed )
491 throw lang::DisposedException();
493 if ( !m_pStorage )
494 throw uno::RuntimeException();
496 bool bResult = m_pStorage->IsContained( aName );
498 if ( m_pStorage->GetError() )
500 m_pStorage->ResetError();
501 throw uno::RuntimeException(); // TODO:
504 return bResult;
508 uno::Type SAL_CALL OLESimpleStorage::getElementType()
510 std::unique_lock aGuard( m_aMutex );
512 if ( m_bDisposed )
513 throw lang::DisposedException();
515 return cppu::UnoType<io::XInputStream>::get();
519 sal_Bool SAL_CALL OLESimpleStorage::hasElements()
521 std::unique_lock aGuard( m_aMutex );
523 if ( m_bDisposed )
524 throw lang::DisposedException();
526 if ( !m_pStorage )
527 throw uno::RuntimeException();
529 SvStorageInfoList aList;
530 m_pStorage->FillInfoList( &aList );
532 if ( m_pStorage->GetError() )
534 m_pStorage->ResetError();
535 throw uno::RuntimeException(); // TODO:
538 return !aList.empty();
542 // XComponent
545 void SAL_CALL OLESimpleStorage::dispose()
547 std::unique_lock aGuard( m_aMutex );
549 if ( m_bDisposed )
550 return;
552 if ( m_aListenersContainer.getLength(aGuard) )
554 lang::EventObject aSource( getXWeak() );
555 m_aListenersContainer.disposeAndClear( aGuard, aSource );
558 m_pStorage.reset();
559 m_pStream.reset();
561 m_xStream.clear();
562 m_xTempStream.clear();
564 m_bDisposed = true;
568 void SAL_CALL OLESimpleStorage::addEventListener(
569 const uno::Reference< lang::XEventListener >& xListener )
571 std::unique_lock aGuard( m_aMutex );
573 if ( m_bDisposed )
574 throw lang::DisposedException();
576 m_aListenersContainer.addInterface( aGuard, xListener );
580 void SAL_CALL OLESimpleStorage::removeEventListener(
581 const uno::Reference< lang::XEventListener >& xListener )
583 std::unique_lock aGuard( m_aMutex );
585 if ( m_bDisposed )
586 throw lang::DisposedException();
588 m_aListenersContainer.removeInterface( aGuard, xListener );
592 // XTransactedObject
595 void SAL_CALL OLESimpleStorage::commit()
597 std::unique_lock aGuard( m_aMutex );
599 if ( m_bDisposed )
600 throw lang::DisposedException();
602 if ( !m_pStorage )
603 throw uno::RuntimeException();
605 if ( !m_bNoTemporaryCopy && !m_xStream.is() )
606 throw io::IOException(); // TODO
608 if ( !m_pStorage->Commit() || m_pStorage->GetError() )
610 m_pStorage->ResetError();
611 throw io::IOException(); // TODO
614 UpdateOriginal_Impl();
618 void SAL_CALL OLESimpleStorage::revert()
620 std::unique_lock aGuard( m_aMutex );
622 if ( m_bDisposed )
623 throw lang::DisposedException();
625 if ( !m_pStorage )
626 throw uno::RuntimeException();
628 if ( !m_bNoTemporaryCopy && !m_xStream.is() )
629 throw io::IOException(); // TODO
631 if ( !m_pStorage->Revert() || m_pStorage->GetError() )
633 m_pStorage->ResetError();
634 throw io::IOException(); // TODO
637 UpdateOriginal_Impl();
641 // XClassifiedObject
644 uno::Sequence< sal_Int8 > SAL_CALL OLESimpleStorage::getClassID()
646 std::unique_lock aGuard( m_aMutex );
648 if ( m_bDisposed )
649 throw lang::DisposedException();
651 if ( !m_pStorage )
652 throw uno::RuntimeException();
654 return m_pStorage->GetClassName().GetByteSequence();
657 OUString SAL_CALL OLESimpleStorage::getClassName()
659 return OUString();
662 void SAL_CALL OLESimpleStorage::setClassInfo( const uno::Sequence< sal_Int8 >& /*aClassID*/,
663 const OUString& /*sClassName*/ )
665 throw lang::NoSupportException();
668 // XServiceInfo
669 OUString SAL_CALL OLESimpleStorage::getImplementationName()
671 return u"com.sun.star.comp.embed.OLESimpleStorage"_ustr;
674 sal_Bool SAL_CALL OLESimpleStorage::supportsService( const OUString& ServiceName )
676 return cppu::supportsService(this, ServiceName);
679 uno::Sequence< OUString > SAL_CALL OLESimpleStorage::getSupportedServiceNames()
681 return { u"com.sun.star.embed.OLESimpleStorage"_ustr };
684 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
685 com_sun_star_comp_embed_OLESimpleStorage(
686 css::uno::XComponentContext *context,
687 css::uno::Sequence<css::uno::Any> const &arguments)
689 return cppu::acquire(new OLESimpleStorage(context, arguments));
692 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */