xref: /core/package/source/xstor/ocompinstream.cxx (revision a6ad198d097fb4a503c8d5831d484ff46721134b)
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 #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>
29 
30 #include "owriteablestream.hxx"
31 
32 using namespace ::com::sun::star;
33 
OInputCompStream(OWriteStream_Impl & aImpl,uno::Reference<io::XInputStream> xStream,const uno::Sequence<beans::PropertyValue> & aProps,sal_Int32 nStorageType)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 )
45 {
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
49 
50     assert(m_xStream.is());
51     assert(m_pByteReader);
52 }
53 
OInputCompStream(uno::Reference<io::XInputStream> xStream,const uno::Sequence<beans::PropertyValue> & aProps,sal_Int32 nStorageType)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 )
64 {
65     assert(m_xStream.is());
66     assert(m_pByteReader);
67 }
68 
~OInputCompStream()69 OInputCompStream::~OInputCompStream()
70 {
71     ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
72 
73     if ( !m_bDisposed )
74     {
75         osl_atomic_increment(&m_refCount);
76         dispose();
77     }
78 }
79 
queryInterface(const uno::Type & rType)80 uno::Any SAL_CALL OInputCompStream::queryInterface( const uno::Type& rType )
81 {
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 ) );
90 
91     if ( aReturn.hasValue() )
92         return aReturn ;
93 
94     if ( m_nStorageType == embed::StorageFormats::OFOPXML )
95     {
96         aReturn = ::cppu::queryInterface
97                     (   rType
98                         ,   static_cast<embed::XRelationshipAccess*> ( this ) );
99 
100         if ( aReturn.hasValue() )
101             return aReturn ;
102     }
103 
104     return OWeakObject::queryInterface( rType );
105 }
106 
readBytes(uno::Sequence<sal_Int8> & aData,sal_Int32 nBytesToRead)107 sal_Int32 SAL_CALL OInputCompStream::readBytes( uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead )
108 {
109     ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
110     if ( m_bDisposed )
111     {
112         SAL_INFO("package.xstor", "Disposed!");
113         throw lang::DisposedException();
114     }
115 
116     return m_xStream->readBytes( aData, nBytesToRead );
117 }
118 
readSomeBytes(uno::Sequence<sal_Int8> & aData,sal_Int32 nMaxBytesToRead)119 sal_Int32 SAL_CALL OInputCompStream::readSomeBytes( uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead )
120 {
121     ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
122     if ( m_bDisposed )
123     {
124         SAL_INFO("package.xstor", "Disposed!");
125         throw lang::DisposedException();
126     }
127 
128     return m_xStream->readSomeBytes( aData, nMaxBytesToRead );
129 
130 }
131 
readSomeBytes(sal_Int8 * aData,sal_Int32 nMaxBytesToRead)132 sal_Int32 OInputCompStream::readSomeBytes( sal_Int8* aData, sal_Int32 nMaxBytesToRead )
133 {
134     ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
135     if ( m_bDisposed )
136     {
137         SAL_INFO("package.xstor", "Disposed!");
138         throw lang::DisposedException();
139     }
140 
141     return m_pByteReader->readSomeBytes( aData, nMaxBytesToRead );
142 
143 }
144 
skipBytes(sal_Int32 nBytesToSkip)145 void SAL_CALL OInputCompStream::skipBytes( sal_Int32 nBytesToSkip )
146 {
147     ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
148     if ( m_bDisposed )
149     {
150         SAL_INFO("package.xstor", "Disposed!");
151         throw lang::DisposedException();
152     }
153 
154     m_xStream->skipBytes( nBytesToSkip );
155 
156 }
157 
available()158 sal_Int32 SAL_CALL OInputCompStream::available(  )
159 {
160     ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
161     if ( m_bDisposed )
162     {
163         SAL_INFO("package.xstor", "Disposed!");
164         throw lang::DisposedException();
165     }
166 
167     return m_xStream->available();
168 
169 }
170 
closeInput()171 void SAL_CALL OInputCompStream::closeInput(  )
172 {
173     dispose();
174 }
175 
getInputStream()176 uno::Reference< io::XInputStream > SAL_CALL OInputCompStream::getInputStream()
177 {
178     ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
179     if ( m_bDisposed )
180     {
181         SAL_INFO("package.xstor", "Disposed!");
182         throw lang::DisposedException();
183     }
184 
185     return this;
186 }
187 
getOutputStream()188 uno::Reference< io::XOutputStream > SAL_CALL OInputCompStream::getOutputStream()
189 {
190     ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
191     if ( m_bDisposed )
192     {
193         SAL_INFO("package.xstor", "Disposed!");
194         throw lang::DisposedException();
195     }
196 
197     return uno::Reference< io::XOutputStream >();
198 }
199 
InternalDispose()200 void OInputCompStream::InternalDispose()
201 {
202     // can be called only by OWriteStream_Impl
203     ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
204     if ( m_bDisposed )
205         return;
206 
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() );
210 
211     if ( m_pInterfaceContainer )
212         m_pInterfaceContainer->disposeAndClear( aSource );
213 
214     try
215     {
216         m_xStream->closeInput();
217     }
218     catch( uno::Exception& )
219     {}
220 
221     m_pImpl = nullptr;
222     m_bDisposed = true;
223 }
224 
dispose()225 void SAL_CALL OInputCompStream::dispose(  )
226 {
227     ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
228     if ( m_bDisposed )
229         return;
230 
231     if ( m_pInterfaceContainer )
232     {
233         lang::EventObject aSource( getXWeak() );
234         m_pInterfaceContainer->disposeAndClear( aSource );
235     }
236 
237     m_xStream->closeInput();
238 
239     if ( m_pImpl )
240     {
241         m_pImpl->InputStreamDisposed( this );
242         m_pImpl = nullptr;
243     }
244 
245     m_bDisposed = true;
246 }
247 
addEventListener(const uno::Reference<lang::XEventListener> & xListener)248 void SAL_CALL OInputCompStream::addEventListener( const uno::Reference< lang::XEventListener >& xListener )
249 {
250     ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
251     if ( m_bDisposed )
252     {
253         SAL_INFO("package.xstor", "Disposed!");
254         throw lang::DisposedException();
255     }
256 
257     if ( !m_pInterfaceContainer )
258         m_pInterfaceContainer.reset( new ::comphelper::OInterfaceContainerHelper3<css::lang::XEventListener>( m_xMutex->GetMutex() ) );
259 
260     m_pInterfaceContainer->addInterface( xListener );
261 }
262 
removeEventListener(const uno::Reference<lang::XEventListener> & xListener)263 void SAL_CALL OInputCompStream::removeEventListener( const uno::Reference< lang::XEventListener >& xListener )
264 {
265     ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
266     if ( m_bDisposed )
267     {
268         SAL_INFO("package.xstor", "Disposed!");
269         throw lang::DisposedException();
270     }
271 
272     if ( m_pInterfaceContainer )
273         m_pInterfaceContainer->removeInterface( xListener );
274 }
275 
hasByID(const OUString & sID)276 sal_Bool SAL_CALL OInputCompStream::hasByID(  const OUString& sID )
277 {
278     ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
279 
280     if ( m_bDisposed )
281     {
282         SAL_INFO("package.xstor", "Disposed!");
283         throw lang::DisposedException();
284     }
285 
286     if ( m_nStorageType != embed::StorageFormats::OFOPXML )
287         throw uno::RuntimeException();
288 
289     try
290     {
291         getRelationshipByID( sID );
292         return true;
293     }
294     catch( container::NoSuchElementException& )
295     {}
296 
297     return false;
298 }
299 
300 namespace
301 {
302 
lcl_findPairByName(const uno::Sequence<beans::StringPair> & rSeq,const OUString & rName)303 const beans::StringPair* lcl_findPairByName(const uno::Sequence<beans::StringPair>& rSeq, const OUString& rName)
304 {
305     return std::find_if(rSeq.begin(), rSeq.end(),
306         [&rName](const beans::StringPair& rPair) { return rPair.First == rName; });
307 }
308 
309 }
310 
getTargetByID(const OUString & sID)311 OUString SAL_CALL OInputCompStream::getTargetByID(  const OUString& sID  )
312 {
313     ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
314 
315     if ( m_bDisposed )
316     {
317         SAL_INFO("package.xstor", "Disposed!");
318         throw lang::DisposedException();
319     }
320 
321     if ( m_nStorageType != embed::StorageFormats::OFOPXML )
322         throw uno::RuntimeException();
323 
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;
328 
329     return OUString();
330 }
331 
getTypeByID(const OUString & sID)332 OUString SAL_CALL OInputCompStream::getTypeByID(  const OUString& sID  )
333 {
334     ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
335 
336     if ( m_bDisposed )
337     {
338         SAL_INFO("package.xstor", "Disposed!");
339         throw lang::DisposedException();
340     }
341 
342     if ( m_nStorageType != embed::StorageFormats::OFOPXML )
343         throw uno::RuntimeException();
344 
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;
349 
350     return OUString();
351 }
352 
getRelationshipByID(const OUString & sID)353 uno::Sequence< beans::StringPair > SAL_CALL OInputCompStream::getRelationshipByID(  const OUString& sID  )
354 {
355     ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
356 
357     if ( m_bDisposed )
358     {
359         SAL_INFO("package.xstor", "Disposed!");
360         throw lang::DisposedException();
361     }
362 
363     if ( m_nStorageType != embed::StorageFormats::OFOPXML )
364         throw uno::RuntimeException();
365 
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;
374 
375     throw container::NoSuchElementException();
376 }
377 
getRelationshipsByType(const OUString & sType)378 uno::Sequence< uno::Sequence< beans::StringPair > > SAL_CALL OInputCompStream::getRelationshipsByType(  const OUString& sType  )
379 {
380     ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
381 
382     if ( m_bDisposed )
383     {
384         SAL_INFO("package.xstor", "Disposed!");
385         throw lang::DisposedException();
386     }
387 
388     if ( m_nStorageType != embed::StorageFormats::OFOPXML )
389         throw uno::RuntimeException();
390 
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());
396 
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(); });
400 
401     return comphelper::containerToSequence(aResult);
402 }
403 
getAllRelationships()404 uno::Sequence< uno::Sequence< beans::StringPair > > SAL_CALL OInputCompStream::getAllRelationships()
405 {
406     ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
407 
408     if ( m_bDisposed )
409     {
410         SAL_INFO("package.xstor", "Disposed!");
411         throw lang::DisposedException();
412     }
413 
414     if ( m_nStorageType != embed::StorageFormats::OFOPXML )
415         throw uno::RuntimeException();
416 
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))
421     {
422         uno::Sequence< uno::Sequence< beans::StringPair > > aResult;
423         if (pProp->Value >>= aResult)
424             return aResult;
425     }
426 
427     throw io::IOException(u"relations info could not be read"_ustr); // the relations info could not be read
428 }
429 
insertRelationshipByID(const OUString &,const uno::Sequence<beans::StringPair> &,sal_Bool)430 void SAL_CALL OInputCompStream::insertRelationshipByID(  const OUString& /*sID*/, const uno::Sequence< beans::StringPair >& /*aEntry*/, sal_Bool /*bReplace*/  )
431 {
432     ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
433 
434     if ( m_bDisposed )
435     {
436         SAL_INFO("package.xstor", "Disposed!");
437         throw lang::DisposedException();
438     }
439 
440     if ( m_nStorageType != embed::StorageFormats::OFOPXML )
441         throw uno::RuntimeException();
442 
443     throw io::IOException(); // TODO: Access denied
444 }
445 
removeRelationshipByID(const OUString &)446 void SAL_CALL OInputCompStream::removeRelationshipByID(  const OUString& /*sID*/  )
447 {
448     ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
449 
450     if ( m_bDisposed )
451     {
452         SAL_INFO("package.xstor", "Disposed!");
453         throw lang::DisposedException();
454     }
455 
456     if ( m_nStorageType != embed::StorageFormats::OFOPXML )
457         throw uno::RuntimeException();
458 
459     throw io::IOException(); // TODO: Access denied
460 }
461 
insertRelationships(const uno::Sequence<uno::Sequence<beans::StringPair>> &,sal_Bool)462 void SAL_CALL OInputCompStream::insertRelationships(  const uno::Sequence< uno::Sequence< beans::StringPair > >& /*aEntries*/, sal_Bool /*bReplace*/  )
463 {
464     ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
465 
466     if ( m_bDisposed )
467     {
468         SAL_INFO("package.xstor", "Disposed!");
469         throw lang::DisposedException();
470     }
471 
472     if ( m_nStorageType != embed::StorageFormats::OFOPXML )
473         throw uno::RuntimeException();
474 
475     throw io::IOException(); // TODO: Access denied
476 }
477 
clearRelationships()478 void SAL_CALL OInputCompStream::clearRelationships()
479 {
480     ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
481 
482     if ( m_bDisposed )
483     {
484         SAL_INFO("package.xstor", "Disposed!");
485         throw lang::DisposedException();
486     }
487 
488     if ( m_nStorageType != embed::StorageFormats::OFOPXML )
489         throw uno::RuntimeException();
490 
491     throw io::IOException(); // TODO: Access denied
492 }
493 
getPropertySetInfo()494 uno::Reference< beans::XPropertySetInfo > SAL_CALL OInputCompStream::getPropertySetInfo()
495 {
496     ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
497 
498     if ( m_bDisposed )
499     {
500         SAL_INFO("package.xstor", "Disposed!");
501         throw lang::DisposedException();
502     }
503 
504     //TODO:
505     return uno::Reference< beans::XPropertySetInfo >();
506 }
507 
setPropertyValue(const OUString & aPropertyName,const uno::Any &)508 void SAL_CALL OInputCompStream::setPropertyValue( const OUString& aPropertyName, const uno::Any& /*aValue*/ )
509 {
510     ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
511 
512     if ( m_bDisposed )
513     {
514         SAL_INFO("package.xstor", "Disposed!");
515         throw lang::DisposedException();
516     }
517 
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
522 
523     throw beans::UnknownPropertyException(aPropertyName); // TODO
524 }
525 
getPropertyValue(const OUString & aProp)526 uno::Any SAL_CALL OInputCompStream::getPropertyValue( const OUString& aProp )
527 {
528     ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
529 
530     if ( m_bDisposed )
531     {
532         SAL_INFO("package.xstor", "Disposed!");
533         throw lang::DisposedException();
534     }
535 
536     OUString aPropertyName;
537     if ( aProp == "IsEncrypted" )
538         aPropertyName = "Encrypted";
539     else
540         aPropertyName = aProp;
541 
542     if ( aPropertyName == "RelationsInfo" )
543         throw beans::UnknownPropertyException(aPropertyName); // TODO
544 
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;
550 
551     throw beans::UnknownPropertyException(aPropertyName); // TODO
552 }
553 
addPropertyChangeListener(const OUString &,const uno::Reference<beans::XPropertyChangeListener> &)554 void SAL_CALL OInputCompStream::addPropertyChangeListener(
555     const OUString& /*aPropertyName*/,
556     const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/ )
557 {
558     ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
559 
560     if ( m_bDisposed )
561     {
562         SAL_INFO("package.xstor", "Disposed!");
563         throw lang::DisposedException();
564     }
565 
566     //TODO:
567 }
568 
removePropertyChangeListener(const OUString &,const uno::Reference<beans::XPropertyChangeListener> &)569 void SAL_CALL OInputCompStream::removePropertyChangeListener(
570     const OUString& /*aPropertyName*/,
571     const uno::Reference< beans::XPropertyChangeListener >& /*aListener*/ )
572 {
573     ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
574 
575     if ( m_bDisposed )
576     {
577         SAL_INFO("package.xstor", "Disposed!");
578         throw lang::DisposedException();
579     }
580 
581     //TODO:
582 }
583 
addVetoableChangeListener(const OUString &,const uno::Reference<beans::XVetoableChangeListener> &)584 void SAL_CALL OInputCompStream::addVetoableChangeListener(
585     const OUString& /*PropertyName*/,
586     const uno::Reference< beans::XVetoableChangeListener >& /*aListener*/ )
587 {
588     ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
589 
590     if ( m_bDisposed )
591     {
592         SAL_INFO("package.xstor", "Disposed!");
593         throw lang::DisposedException();
594     }
595 
596     //TODO:
597 }
598 
removeVetoableChangeListener(const OUString &,const uno::Reference<beans::XVetoableChangeListener> &)599 void SAL_CALL OInputCompStream::removeVetoableChangeListener(
600     const OUString& /*PropertyName*/,
601     const uno::Reference< beans::XVetoableChangeListener >& /*aListener*/ )
602 {
603     ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
604 
605     if ( m_bDisposed )
606     {
607         SAL_INFO("package.xstor", "Disposed!");
608         throw lang::DisposedException();
609     }
610 
611     //TODO:
612 }
613 
614 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
615