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