cid#1607171 Data race condition
[LibreOffice.git] / package / source / xstor / ocompinstream.cxx
blobb71b8ef996979a02603ae71ef3d6292abe0fd16e
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 "ocompinstream.hxx"
21 #include <com/sun/star/embed/StorageFormats.hpp>
22 #include <com/sun/star/io/IOException.hpp>
23 #include <com/sun/star/lang/DisposedException.hpp>
24 #include <comphelper/sequence.hxx>
25 #include <cppuhelper/queryinterface.hxx>
26 #include <osl/diagnose.h>
27 #include <sal/log.hxx>
28 #include <utility>
30 #include "owriteablestream.hxx"
32 using namespace ::com::sun::star;
34 OInputCompStream::OInputCompStream( OWriteStream_Impl& aImpl,
35 uno::Reference < io::XInputStream > xStream,
36 const uno::Sequence< beans::PropertyValue >& aProps,
37 sal_Int32 nStorageType )
38 : m_pImpl( &aImpl )
39 , m_xMutex( m_pImpl->m_xMutex )
40 , m_xStream(std::move( xStream ))
41 , m_pByteReader( dynamic_cast<comphelper::ByteReader*>(m_xStream.get()) )
42 , m_aProperties( aProps )
43 , m_bDisposed( false )
44 , m_nStorageType( nStorageType )
46 OSL_ENSURE( m_pImpl->m_xMutex.is(), "No mutex is provided!" );
47 if ( !m_pImpl->m_xMutex.is() )
48 throw uno::RuntimeException(); // just a disaster
50 assert(m_xStream.is());
51 assert(m_pByteReader);
54 OInputCompStream::OInputCompStream( uno::Reference < io::XInputStream > xStream,
55 const uno::Sequence< beans::PropertyValue >& aProps,
56 sal_Int32 nStorageType )
57 : m_pImpl( nullptr )
58 , m_xMutex( new comphelper::RefCountedMutex )
59 , m_xStream(std::move( xStream ))
60 , m_pByteReader( dynamic_cast<comphelper::ByteReader*>(m_xStream.get()) )
61 , m_aProperties( aProps )
62 , m_bDisposed( false )
63 , m_nStorageType( nStorageType )
65 assert(m_xStream.is());
66 assert(m_pByteReader);
69 OInputCompStream::~OInputCompStream()
71 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
73 if ( !m_bDisposed )
75 osl_atomic_increment(&m_refCount);
76 dispose();
80 uno::Any SAL_CALL OInputCompStream::queryInterface( const uno::Type& rType )
82 // common interfaces
83 uno::Any aReturn = ::cppu::queryInterface
84 ( rType
85 , static_cast<io::XInputStream*> ( this )
86 , static_cast<io::XStream*> ( this )
87 , static_cast<lang::XComponent*> ( this )
88 , static_cast<beans::XPropertySet*> ( this )
89 , static_cast<embed::XExtendedStorageStream*> ( this ) );
91 if ( aReturn.hasValue() )
92 return aReturn ;
94 if ( m_nStorageType == embed::StorageFormats::OFOPXML )
96 aReturn = ::cppu::queryInterface
97 ( rType
98 , static_cast<embed::XRelationshipAccess*> ( this ) );
100 if ( aReturn.hasValue() )
101 return aReturn ;
104 return OWeakObject::queryInterface( rType );
107 sal_Int32 SAL_CALL OInputCompStream::readBytes( uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead )
109 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
110 if ( m_bDisposed )
112 SAL_INFO("package.xstor", "Disposed!");
113 throw lang::DisposedException();
116 return m_xStream->readBytes( aData, nBytesToRead );
119 sal_Int32 SAL_CALL OInputCompStream::readSomeBytes( uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead )
121 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
122 if ( m_bDisposed )
124 SAL_INFO("package.xstor", "Disposed!");
125 throw lang::DisposedException();
128 return m_xStream->readSomeBytes( aData, nMaxBytesToRead );
132 sal_Int32 OInputCompStream::readSomeBytes( sal_Int8* aData, sal_Int32 nMaxBytesToRead )
134 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
135 if ( m_bDisposed )
137 SAL_INFO("package.xstor", "Disposed!");
138 throw lang::DisposedException();
141 return m_pByteReader->readSomeBytes( aData, nMaxBytesToRead );
145 void SAL_CALL OInputCompStream::skipBytes( sal_Int32 nBytesToSkip )
147 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
148 if ( m_bDisposed )
150 SAL_INFO("package.xstor", "Disposed!");
151 throw lang::DisposedException();
154 m_xStream->skipBytes( nBytesToSkip );
158 sal_Int32 SAL_CALL OInputCompStream::available( )
160 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
161 if ( m_bDisposed )
163 SAL_INFO("package.xstor", "Disposed!");
164 throw lang::DisposedException();
167 return m_xStream->available();
171 void SAL_CALL OInputCompStream::closeInput( )
173 dispose();
176 uno::Reference< io::XInputStream > SAL_CALL OInputCompStream::getInputStream()
178 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
179 if ( m_bDisposed )
181 SAL_INFO("package.xstor", "Disposed!");
182 throw lang::DisposedException();
185 return this;
188 uno::Reference< io::XOutputStream > SAL_CALL OInputCompStream::getOutputStream()
190 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
191 if ( m_bDisposed )
193 SAL_INFO("package.xstor", "Disposed!");
194 throw lang::DisposedException();
197 return uno::Reference< io::XOutputStream >();
200 void OInputCompStream::InternalDispose()
202 // can be called only by OWriteStream_Impl
203 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
204 if ( m_bDisposed )
205 return;
207 // the source object is also a kind of locker for the current object
208 // since the listeners could dispose the object while being notified
209 lang::EventObject aSource( getXWeak() );
211 if ( m_pInterfaceContainer )
212 m_pInterfaceContainer->disposeAndClear( aSource );
216 m_xStream->closeInput();
218 catch( uno::Exception& )
221 m_pImpl = nullptr;
222 m_bDisposed = true;
225 void SAL_CALL OInputCompStream::dispose( )
227 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
228 if ( m_bDisposed )
229 return;
231 if ( m_pInterfaceContainer )
233 lang::EventObject aSource( getXWeak() );
234 m_pInterfaceContainer->disposeAndClear( aSource );
237 m_xStream->closeInput();
239 if ( m_pImpl )
241 m_pImpl->InputStreamDisposed( this );
242 m_pImpl = nullptr;
245 m_bDisposed = true;
248 void SAL_CALL OInputCompStream::addEventListener( const uno::Reference< lang::XEventListener >& xListener )
250 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
251 if ( m_bDisposed )
253 SAL_INFO("package.xstor", "Disposed!");
254 throw lang::DisposedException();
257 if ( !m_pInterfaceContainer )
258 m_pInterfaceContainer.reset( new ::comphelper::OInterfaceContainerHelper3<css::lang::XEventListener>( m_xMutex->GetMutex() ) );
260 m_pInterfaceContainer->addInterface( xListener );
263 void SAL_CALL OInputCompStream::removeEventListener( const uno::Reference< lang::XEventListener >& xListener )
265 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
266 if ( m_bDisposed )
268 SAL_INFO("package.xstor", "Disposed!");
269 throw lang::DisposedException();
272 if ( m_pInterfaceContainer )
273 m_pInterfaceContainer->removeInterface( xListener );
276 sal_Bool SAL_CALL OInputCompStream::hasByID( const OUString& sID )
278 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
280 if ( m_bDisposed )
282 SAL_INFO("package.xstor", "Disposed!");
283 throw lang::DisposedException();
286 if ( m_nStorageType != embed::StorageFormats::OFOPXML )
287 throw uno::RuntimeException();
291 getRelationshipByID( sID );
292 return true;
294 catch( container::NoSuchElementException& )
297 return false;
300 namespace
303 const beans::StringPair* lcl_findPairByName(const uno::Sequence<beans::StringPair>& rSeq, const OUString& rName)
305 return std::find_if(rSeq.begin(), rSeq.end(),
306 [&rName](const beans::StringPair& rPair) { return rPair.First == rName; });
311 OUString SAL_CALL OInputCompStream::getTargetByID( const OUString& sID )
313 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
315 if ( m_bDisposed )
317 SAL_INFO("package.xstor", "Disposed!");
318 throw lang::DisposedException();
321 if ( m_nStorageType != embed::StorageFormats::OFOPXML )
322 throw uno::RuntimeException();
324 const uno::Sequence< beans::StringPair > aSeq = getRelationshipByID( sID );
325 auto pRel = lcl_findPairByName(aSeq, u"Target"_ustr);
326 if (pRel != aSeq.end())
327 return pRel->Second;
329 return OUString();
332 OUString SAL_CALL OInputCompStream::getTypeByID( const OUString& sID )
334 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
336 if ( m_bDisposed )
338 SAL_INFO("package.xstor", "Disposed!");
339 throw lang::DisposedException();
342 if ( m_nStorageType != embed::StorageFormats::OFOPXML )
343 throw uno::RuntimeException();
345 const uno::Sequence< beans::StringPair > aSeq = getRelationshipByID( sID );
346 auto pRel = lcl_findPairByName(aSeq, u"Type"_ustr);
347 if (pRel != aSeq.end())
348 return pRel->Second;
350 return OUString();
353 uno::Sequence< beans::StringPair > SAL_CALL OInputCompStream::getRelationshipByID( const OUString& sID )
355 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
357 if ( m_bDisposed )
359 SAL_INFO("package.xstor", "Disposed!");
360 throw lang::DisposedException();
363 if ( m_nStorageType != embed::StorageFormats::OFOPXML )
364 throw uno::RuntimeException();
366 // TODO/LATER: in future the unification of the ID could be checked
367 const uno::Sequence< uno::Sequence< beans::StringPair > > aSeq = getAllRelationships();
368 const beans::StringPair aIDRel(u"Id"_ustr, sID);
369 auto pRel = std::find_if(aSeq.begin(), aSeq.end(),
370 [&aIDRel](const uno::Sequence<beans::StringPair>& rRel){
371 return std::find(rRel.begin(), rRel.end(), aIDRel) != rRel.end(); });
372 if (pRel != aSeq.end())
373 return *pRel;
375 throw container::NoSuchElementException();
378 uno::Sequence< uno::Sequence< beans::StringPair > > SAL_CALL OInputCompStream::getRelationshipsByType( const OUString& sType )
380 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
382 if ( m_bDisposed )
384 SAL_INFO("package.xstor", "Disposed!");
385 throw lang::DisposedException();
388 if ( m_nStorageType != embed::StorageFormats::OFOPXML )
389 throw uno::RuntimeException();
391 // TODO/LATER: in future the unification of the ID could be checked
392 const uno::Sequence< uno::Sequence< beans::StringPair > > aSeq = getAllRelationships();
393 const beans::StringPair aTypeRel(u"Type"_ustr, sType);
394 std::vector< uno::Sequence<beans::StringPair> > aResult;
395 aResult.reserve(aSeq.getLength());
397 std::copy_if(aSeq.begin(), aSeq.end(), std::back_inserter(aResult),
398 [&aTypeRel](const uno::Sequence<beans::StringPair>& rRel) {
399 return std::find(rRel.begin(), rRel.end(), aTypeRel) != rRel.end(); });
401 return comphelper::containerToSequence(aResult);
404 uno::Sequence< uno::Sequence< beans::StringPair > > SAL_CALL OInputCompStream::getAllRelationships()
406 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
408 if ( m_bDisposed )
410 SAL_INFO("package.xstor", "Disposed!");
411 throw lang::DisposedException();
414 if ( m_nStorageType != embed::StorageFormats::OFOPXML )
415 throw uno::RuntimeException();
417 // TODO/LATER: in future the information could be taken directly from m_pImpl when possible
418 auto pProp = std::find_if(std::cbegin(m_aProperties), std::cend(m_aProperties),
419 [](const beans::PropertyValue& rProp) { return rProp.Name == "RelationsInfo"; });
420 if (pProp != std::cend(m_aProperties))
422 uno::Sequence< uno::Sequence< beans::StringPair > > aResult;
423 if (pProp->Value >>= aResult)
424 return aResult;
427 throw io::IOException(u"relations info could not be read"_ustr); // the relations info could not be read
430 void SAL_CALL OInputCompStream::insertRelationshipByID( const OUString& /*sID*/, const uno::Sequence< beans::StringPair >& /*aEntry*/, sal_Bool /*bReplace*/ )
432 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
434 if ( m_bDisposed )
436 SAL_INFO("package.xstor", "Disposed!");
437 throw lang::DisposedException();
440 if ( m_nStorageType != embed::StorageFormats::OFOPXML )
441 throw uno::RuntimeException();
443 throw io::IOException(); // TODO: Access denied
446 void SAL_CALL OInputCompStream::removeRelationshipByID( const OUString& /*sID*/ )
448 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
450 if ( m_bDisposed )
452 SAL_INFO("package.xstor", "Disposed!");
453 throw lang::DisposedException();
456 if ( m_nStorageType != embed::StorageFormats::OFOPXML )
457 throw uno::RuntimeException();
459 throw io::IOException(); // TODO: Access denied
462 void SAL_CALL OInputCompStream::insertRelationships( const uno::Sequence< uno::Sequence< beans::StringPair > >& /*aEntries*/, sal_Bool /*bReplace*/ )
464 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
466 if ( m_bDisposed )
468 SAL_INFO("package.xstor", "Disposed!");
469 throw lang::DisposedException();
472 if ( m_nStorageType != embed::StorageFormats::OFOPXML )
473 throw uno::RuntimeException();
475 throw io::IOException(); // TODO: Access denied
478 void SAL_CALL OInputCompStream::clearRelationships()
480 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
482 if ( m_bDisposed )
484 SAL_INFO("package.xstor", "Disposed!");
485 throw lang::DisposedException();
488 if ( m_nStorageType != embed::StorageFormats::OFOPXML )
489 throw uno::RuntimeException();
491 throw io::IOException(); // TODO: Access denied
494 uno::Reference< beans::XPropertySetInfo > SAL_CALL OInputCompStream::getPropertySetInfo()
496 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
498 if ( m_bDisposed )
500 SAL_INFO("package.xstor", "Disposed!");
501 throw lang::DisposedException();
504 //TODO:
505 return uno::Reference< beans::XPropertySetInfo >();
508 void SAL_CALL OInputCompStream::setPropertyValue( const OUString& aPropertyName, const uno::Any& /*aValue*/ )
510 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
512 if ( m_bDisposed )
514 SAL_INFO("package.xstor", "Disposed!");
515 throw lang::DisposedException();
518 // all the provided properties are accessible
519 if (std::any_of(std::cbegin(m_aProperties), std::cend(m_aProperties),
520 [&aPropertyName](const beans::PropertyValue& rProp) { return rProp.Name == aPropertyName; }))
521 throw beans::PropertyVetoException(); // TODO
523 throw beans::UnknownPropertyException(aPropertyName); // TODO
526 uno::Any SAL_CALL OInputCompStream::getPropertyValue( const OUString& aProp )
528 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
530 if ( m_bDisposed )
532 SAL_INFO("package.xstor", "Disposed!");
533 throw lang::DisposedException();
536 OUString aPropertyName;
537 if ( aProp == "IsEncrypted" )
538 aPropertyName = "Encrypted";
539 else
540 aPropertyName = aProp;
542 if ( aPropertyName == "RelationsInfo" )
543 throw beans::UnknownPropertyException(aPropertyName); // TODO
545 // all the provided properties are accessible
546 auto pProp = std::find_if(std::cbegin(m_aProperties), std::cend(m_aProperties),
547 [&aPropertyName](const beans::PropertyValue& rProp) { return rProp.Name == aPropertyName; });
548 if (pProp != std::cend(m_aProperties))
549 return pProp->Value;
551 throw beans::UnknownPropertyException(aPropertyName); // TODO
554 void SAL_CALL OInputCompStream::addPropertyChangeListener(
555 const OUString& /*aPropertyName*/,
556 const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/ )
558 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
560 if ( m_bDisposed )
562 SAL_INFO("package.xstor", "Disposed!");
563 throw lang::DisposedException();
566 //TODO:
569 void SAL_CALL OInputCompStream::removePropertyChangeListener(
570 const OUString& /*aPropertyName*/,
571 const uno::Reference< beans::XPropertyChangeListener >& /*aListener*/ )
573 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
575 if ( m_bDisposed )
577 SAL_INFO("package.xstor", "Disposed!");
578 throw lang::DisposedException();
581 //TODO:
584 void SAL_CALL OInputCompStream::addVetoableChangeListener(
585 const OUString& /*PropertyName*/,
586 const uno::Reference< beans::XVetoableChangeListener >& /*aListener*/ )
588 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
590 if ( m_bDisposed )
592 SAL_INFO("package.xstor", "Disposed!");
593 throw lang::DisposedException();
596 //TODO:
599 void SAL_CALL OInputCompStream::removeVetoableChangeListener(
600 const OUString& /*PropertyName*/,
601 const uno::Reference< beans::XVetoableChangeListener >& /*aListener*/ )
603 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
605 if ( m_bDisposed )
607 SAL_INFO("package.xstor", "Disposed!");
608 throw lang::DisposedException();
611 //TODO:
614 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */