bump product version to 7.6.3.2-android
[LibreOffice.git] / svl / source / fsstor / fsstorage.cxx
blob65e243d7ddad600badcdb7088ff9a6313198d523
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 <com/sun/star/embed/ElementModes.hpp>
21 #include <com/sun/star/embed/InvalidStorageException.hpp>
22 #include <com/sun/star/embed/StorageWrappedTargetException.hpp>
23 #include <com/sun/star/embed/XTransactedObject.hpp>
24 #include <com/sun/star/packages/NoEncryptionException.hpp>
25 #include <com/sun/star/packages/WrongPasswordException.hpp>
26 #include <com/sun/star/ucb/NameClash.hpp>
27 #include <com/sun/star/ucb/SimpleFileAccess.hpp>
29 #include <com/sun/star/ucb/InteractiveIOException.hpp>
30 #include <com/sun/star/ucb/IOErrorCode.hpp>
31 #include <com/sun/star/container/ElementExistException.hpp>
32 #include <com/sun/star/lang/XComponent.hpp>
33 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
34 #include <com/sun/star/io/IOException.hpp>
35 #include <com/sun/star/io/XTruncate.hpp>
36 #include <com/sun/star/io/TempFile.hpp>
37 #include <com/sun/star/sdbc/XResultSet.hpp>
38 #include <com/sun/star/sdbc/XRow.hpp>
40 #include <comphelper/fileurl.hxx>
41 #include <comphelper/processfactory.hxx>
42 #include <comphelper/storagehelper.hxx>
43 #include <cppuhelper/queryinterface.hxx>
44 #include <cppuhelper/exc_hlp.hxx>
46 #include <osl/diagnose.h>
47 #include <tools/urlobj.hxx>
48 #include <unotools/ucbhelper.hxx>
49 #include <unotools/ucbstreamhelper.hxx>
50 #include <unotools/streamwrap.hxx>
51 #include <unotools/tempfile.hxx>
52 #include <ucbhelper/content.hxx>
54 #include "fsstorage.hxx"
55 #include "oinputstreamcontainer.hxx"
56 #include "ostreamcontainer.hxx"
58 using namespace ::com::sun::star;
60 FSStorage::FSStorage( const ::ucbhelper::Content& aContent,
61 sal_Int32 nMode,
62 uno::Reference< uno::XComponentContext > const & xContext )
63 : m_aURL( aContent.getURL() )
64 , m_aContent( aContent )
65 , m_nMode( nMode )
66 , m_xContext( xContext )
68 OSL_ENSURE( !m_aURL.isEmpty(), "The URL must not be empty" );
69 // TODO: use properties
70 if ( !xContext.is() )
71 throw uno::RuntimeException();
73 GetContent();
76 FSStorage::~FSStorage()
78 std::unique_lock aGuard( m_aMutex );
79 osl_atomic_increment(&m_refCount); // to call dispose
80 try {
81 disposeImpl(aGuard);
83 catch( uno::RuntimeException& )
87 bool FSStorage::MakeFolderNoUI( std::u16string_view rFolder )
89 INetURLObject aURL( rFolder );
90 OUString aTitle = aURL.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::WithCharset );
91 aURL.removeSegment();
92 ::ucbhelper::Content aParent;
93 ::ucbhelper::Content aResultContent;
95 if ( ::ucbhelper::Content::create( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ),
96 uno::Reference< ucb::XCommandEnvironment >(),
97 comphelper::getProcessComponentContext(),
98 aParent ) )
99 return ::utl::UCBContentHelper::MakeFolder( aParent, aTitle, aResultContent );
101 return false;
104 ucbhelper::Content& FSStorage::GetContent()
106 std::unique_lock aGuard( m_aMutex );
107 return m_aContent;
110 void FSStorage::CopyStreamToSubStream( const OUString& aSourceURL,
111 const uno::Reference< embed::XStorage >& xDest,
112 const OUString& aNewEntryName )
114 if ( !xDest.is() )
115 throw uno::RuntimeException();
117 uno::Reference< ucb::XCommandEnvironment > xDummyEnv;
118 ::ucbhelper::Content aSourceContent( aSourceURL, xDummyEnv, comphelper::getProcessComponentContext() );
119 uno::Reference< io::XInputStream > xSourceInput = aSourceContent.openStream();
121 if ( !xSourceInput.is() )
122 throw io::IOException(); // TODO: error handling
124 uno::Reference< io::XStream > xSubStream = xDest->openStreamElement(
125 aNewEntryName,
126 embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
127 if ( !xSubStream.is() )
128 throw uno::RuntimeException();
130 uno::Reference< io::XOutputStream > xDestOutput = xSubStream->getOutputStream();
131 if ( !xDestOutput.is() )
132 throw uno::RuntimeException();
134 ::comphelper::OStorageHelper::CopyInputToOutput( xSourceInput, xDestOutput );
135 xDestOutput->closeOutput();
138 void FSStorage::CopyContentToStorage_Impl(ucbhelper::Content& rContent,
139 const uno::Reference<embed::XStorage>& xDest)
141 // get list of contents of the Content
142 // create cursor for access to children
143 uno::Sequence< OUString > aProps( 2 );
144 OUString* pProps = aProps.getArray();
145 pProps[0] = "TargetURL";
146 pProps[1] = "IsFolder";
150 uno::Reference<sdbc::XResultSet> xResultSet
151 = rContent.createCursor(aProps, ::ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS);
152 uno::Reference< sdbc::XRow > xRow( xResultSet, uno::UNO_QUERY );
153 if ( xResultSet.is() )
155 // go through the list: insert files as streams, insert folders as substorages using recursion
156 while ( xResultSet->next() )
158 OUString aSourceURL( xRow->getString( 1 ) );
159 bool bIsFolder( xRow->getBoolean(2) );
161 // TODO/LATER: not sure whether the entry name must be encoded
162 OUString aNewEntryName( INetURLObject( aSourceURL ).getName( INetURLObject::LAST_SEGMENT,
163 true,
164 INetURLObject::DecodeMechanism::NONE ) );
165 if ( bIsFolder )
167 uno::Reference< embed::XStorage > xSubStorage = xDest->openStorageElement( aNewEntryName,
168 embed::ElementModes::READWRITE );
169 if ( !xSubStorage.is() )
170 throw uno::RuntimeException();
172 uno::Reference< ucb::XCommandEnvironment > xDummyEnv;
173 ::ucbhelper::Content aSourceContent( aSourceURL, xDummyEnv, comphelper::getProcessComponentContext() );
174 CopyContentToStorage_Impl( aSourceContent, xSubStorage );
176 else
178 CopyStreamToSubStream( aSourceURL, xDest, aNewEntryName );
183 uno::Reference< embed::XTransactedObject > xTransact( xDest, uno::UNO_QUERY );
184 if ( xTransact.is() )
185 xTransact->commit();
187 catch( ucb::InteractiveIOException& r )
189 if ( r.Code == ucb::IOErrorCode_NOT_EXISTING )
190 OSL_FAIL( "The folder does not exist!" );
191 else
192 throw;
196 // XInterface
198 uno::Any SAL_CALL FSStorage::queryInterface( const uno::Type& rType )
200 uno::Any aReturn = ::cppu::queryInterface
201 ( rType
202 , static_cast<lang::XTypeProvider*> ( this )
203 , static_cast<embed::XStorage*> ( this )
204 , static_cast<embed::XHierarchicalStorageAccess*> ( this )
205 , static_cast<container::XNameAccess*> ( this )
206 , static_cast<container::XElementAccess*> ( this )
207 , static_cast<lang::XComponent*> ( this )
208 , static_cast<beans::XPropertySet*> ( this ) );
210 if ( aReturn.hasValue() )
211 return aReturn ;
213 return OWeakObject::queryInterface( rType );
216 void SAL_CALL FSStorage::acquire() noexcept
218 OWeakObject::acquire();
221 void SAL_CALL FSStorage::release() noexcept
223 OWeakObject::release();
226 // XTypeProvider
228 uno::Sequence< uno::Type > SAL_CALL FSStorage::getTypes()
230 static const uno::Sequence<uno::Type> aTypes {
231 cppu::UnoType<lang::XTypeProvider>::get(),
232 cppu::UnoType<embed::XStorage>::get(),
233 cppu::UnoType<embed::XHierarchicalStorageAccess>::get(),
234 cppu::UnoType<beans::XPropertySet>::get() };
235 return aTypes;
238 uno::Sequence< sal_Int8 > SAL_CALL FSStorage::getImplementationId()
240 return css::uno::Sequence<sal_Int8>();
243 // XStorage
245 void SAL_CALL FSStorage::copyToStorage( const uno::Reference< embed::XStorage >& xDest )
247 std::unique_lock aGuard( m_aMutex );
249 if ( !xDest.is() || xDest == uno::Reference< uno::XInterface >( static_cast< OWeakObject*> ( this ), uno::UNO_QUERY ) )
250 throw lang::IllegalArgumentException(); // TODO:
254 CopyContentToStorage_Impl( m_aContent, xDest );
256 catch( embed::InvalidStorageException& )
258 throw;
260 catch( lang::IllegalArgumentException& )
262 throw;
264 catch( embed::StorageWrappedTargetException& )
266 throw;
268 catch( io::IOException& )
270 throw;
272 catch( uno::RuntimeException& )
274 throw;
276 catch( uno::Exception& )
278 uno::Any aCaught( ::cppu::getCaughtException() );
279 throw embed::StorageWrappedTargetException("Can't copy raw stream",
280 uno::Reference< io::XInputStream >(),
281 aCaught );
285 uno::Reference< io::XStream > SAL_CALL FSStorage::openStreamElement(
286 const OUString& aStreamName, sal_Int32 nOpenMode )
288 std::unique_lock aGuard( m_aMutex );
289 return openStreamElementImpl(aGuard, aStreamName, nOpenMode);
292 uno::Reference< io::XStream > FSStorage::openStreamElementImpl(
293 std::unique_lock<std::mutex>& /*rGuard*/,
294 std::u16string_view aStreamName, sal_Int32 nOpenMode )
296 // TODO/LATER: may need possibility to create folder if it was removed, since the folder can not be locked
297 INetURLObject aFileURL( m_aURL );
298 aFileURL.Append( aStreamName );
300 if ( ::utl::UCBContentHelper::IsFolder( aFileURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) )
301 throw io::IOException();
303 if ( ( nOpenMode & embed::ElementModes::NOCREATE )
304 && !::utl::UCBContentHelper::IsDocument( aFileURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) )
305 throw io::IOException(); // TODO:
307 uno::Reference< ucb::XCommandEnvironment > xDummyEnv; // TODO: provide InteractionHandler if any
308 uno::Reference< io::XStream > xResult;
311 if ( nOpenMode & embed::ElementModes::WRITE )
313 if ( aFileURL.GetProtocol() == INetProtocol::File )
315 uno::Reference<ucb::XSimpleFileAccess3> xSimpleFileAccess(
316 ucb::SimpleFileAccess::create( m_xContext ) );
317 xResult = xSimpleFileAccess->openFileReadWrite( aFileURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
319 else
321 // TODO: test whether it really works for http and fwp
322 std::unique_ptr<SvStream> pStream = ::utl::UcbStreamHelper::CreateStream( aFileURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ),
323 StreamMode::STD_WRITE );
324 if ( pStream && !pStream->GetError() )
325 xResult.set( new ::utl::OStreamWrapper( std::move(pStream) ) );
328 if ( !xResult.is() )
329 throw io::IOException();
331 if ( nOpenMode & embed::ElementModes::TRUNCATE )
333 uno::Reference< io::XTruncate > xTrunc( xResult->getOutputStream(), uno::UNO_QUERY_THROW );
334 xTrunc->truncate();
337 else
339 if ( ( nOpenMode & embed::ElementModes::TRUNCATE )
340 || !::utl::UCBContentHelper::IsDocument( aFileURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) )
341 throw io::IOException(); // TODO: access denied
343 ::ucbhelper::Content aResultContent( aFileURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), xDummyEnv, comphelper::getProcessComponentContext() );
344 uno::Reference< io::XInputStream > xInStream = aResultContent.openStream();
345 xResult = new OFSInputStreamContainer(xInStream);
348 catch( embed::InvalidStorageException& )
350 throw;
352 catch( lang::IllegalArgumentException& )
354 throw;
356 catch( packages::WrongPasswordException& )
358 throw;
360 catch( embed::StorageWrappedTargetException& )
362 throw;
364 catch( io::IOException& )
366 throw;
368 catch( uno::RuntimeException& )
370 throw;
372 catch( uno::Exception& )
374 uno::Any aCaught( ::cppu::getCaughtException() );
375 throw embed::StorageWrappedTargetException("Can't copy raw stream",
376 uno::Reference< io::XInputStream >(),
377 aCaught );
380 return xResult;
383 uno::Reference< io::XStream > SAL_CALL FSStorage::openEncryptedStreamElement(
384 const OUString&, sal_Int32, const OUString& )
386 throw packages::NoEncryptionException();
389 uno::Reference< embed::XStorage > SAL_CALL FSStorage::openStorageElement(
390 const OUString& aStorName, sal_Int32 nStorageMode )
392 std::unique_lock aGuard( m_aMutex );
393 return openStorageElementImpl(aGuard, aStorName, nStorageMode);
396 uno::Reference< embed::XStorage > FSStorage::openStorageElementImpl(
397 std::unique_lock<std::mutex>& /*rGuard*/,
398 std::u16string_view aStorName, sal_Int32 nStorageMode )
400 if ( ( nStorageMode & embed::ElementModes::WRITE )
401 && !( m_nMode & embed::ElementModes::WRITE ) )
402 throw io::IOException(); // TODO: error handling
404 // TODO/LATER: may need possibility to create folder if it was removed, since the folder can not be locked
405 INetURLObject aFolderURL( m_aURL );
406 aFolderURL.Append( aStorName );
408 bool bFolderExists = ::utl::UCBContentHelper::IsFolder( aFolderURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
409 if ( !bFolderExists && ::utl::UCBContentHelper::IsDocument( aFolderURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) )
410 throw io::IOException(); // TODO:
412 if ( ( nStorageMode & embed::ElementModes::NOCREATE ) && !bFolderExists )
413 throw io::IOException(); // TODO:
415 uno::Reference< ucb::XCommandEnvironment > xDummyEnv; // TODO: provide InteractionHandler if any
416 uno::Reference< embed::XStorage > xResult;
419 if ( nStorageMode & embed::ElementModes::WRITE )
421 if ( ( nStorageMode & embed::ElementModes::TRUNCATE ) && bFolderExists )
423 ::utl::UCBContentHelper::Kill( aFolderURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
424 bFolderExists =
425 MakeFolderNoUI( aFolderURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); // TODO: not atomic :(
427 else if ( !bFolderExists )
429 bFolderExists =
430 MakeFolderNoUI( aFolderURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); // TODO: not atomic :(
433 else if ( nStorageMode & embed::ElementModes::TRUNCATE )
434 throw io::IOException(); // TODO: access denied
436 if ( !bFolderExists )
437 throw io::IOException(); // there is no such folder
439 ::ucbhelper::Content aResultContent( aFolderURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), xDummyEnv, comphelper::getProcessComponentContext() );
440 xResult = new FSStorage( aResultContent, nStorageMode, m_xContext );
442 catch( embed::InvalidStorageException& )
444 throw;
446 catch( lang::IllegalArgumentException& )
448 throw;
450 catch( embed::StorageWrappedTargetException& )
452 throw;
454 catch( io::IOException& )
456 throw;
458 catch( uno::RuntimeException& )
460 throw;
462 catch( uno::Exception& )
464 uno::Any aCaught( ::cppu::getCaughtException() );
465 throw embed::StorageWrappedTargetException("Can't copy raw stream",
466 uno::Reference< io::XInputStream >(),
467 aCaught );
470 return xResult;
473 uno::Reference< io::XStream > SAL_CALL FSStorage::cloneStreamElement( const OUString& aStreamName )
475 std::unique_lock aGuard( m_aMutex );
477 // TODO/LATER: may need possibility to create folder if it was removed, since the folder can not be locked
478 INetURLObject aFileURL( m_aURL );
479 aFileURL.Append( aStreamName );
481 uno::Reference < io::XStream > xTempResult;
484 uno::Reference< ucb::XCommandEnvironment > xDummyEnv;
485 ::ucbhelper::Content aResultContent( aFileURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), xDummyEnv, comphelper::getProcessComponentContext() );
486 uno::Reference< io::XInputStream > xInStream = aResultContent.openStream();
488 xTempResult = new utl::TempFileFastService;
489 uno::Reference < io::XOutputStream > xTempOut = xTempResult->getOutputStream();
490 uno::Reference < io::XInputStream > xTempIn = xTempResult->getInputStream();
492 ::comphelper::OStorageHelper::CopyInputToOutput( xInStream, xTempOut );
493 xTempOut->closeOutput();
495 catch( embed::InvalidStorageException& )
497 throw;
499 catch( lang::IllegalArgumentException& )
501 throw;
503 catch( packages::WrongPasswordException& )
505 throw;
507 catch( io::IOException& )
509 throw;
511 catch( embed::StorageWrappedTargetException& )
513 throw;
515 catch( uno::RuntimeException& )
517 throw;
519 catch( uno::Exception& )
521 uno::Any aCaught( ::cppu::getCaughtException() );
522 throw embed::StorageWrappedTargetException("Can't copy raw stream",
523 uno::Reference< io::XInputStream >(),
524 aCaught );
527 return xTempResult;
530 uno::Reference< io::XStream > SAL_CALL FSStorage::cloneEncryptedStreamElement(
531 const OUString&,
532 const OUString& )
534 throw packages::NoEncryptionException();
537 void SAL_CALL FSStorage::copyLastCommitTo(
538 const uno::Reference< embed::XStorage >& xTargetStorage )
540 copyToStorage( xTargetStorage );
543 void SAL_CALL FSStorage::copyStorageElementLastCommitTo(
544 const OUString& aStorName,
545 const uno::Reference< embed::XStorage >& xTargetStorage )
547 std::unique_lock aGuard( m_aMutex );
549 uno::Reference< embed::XStorage > xSourceStor( openStorageElement( aStorName, embed::ElementModes::READ ),
550 uno::UNO_SET_THROW );
551 xSourceStor->copyToStorage( xTargetStorage );
554 sal_Bool SAL_CALL FSStorage::isStreamElement( const OUString& aElementName )
556 std::unique_lock aGuard( m_aMutex );
558 INetURLObject aURL( m_aURL );
559 aURL.Append( aElementName );
561 return !::utl::UCBContentHelper::IsFolder( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
564 sal_Bool SAL_CALL FSStorage::isStorageElement( const OUString& aElementName )
566 std::unique_lock aGuard( m_aMutex );
568 INetURLObject aURL( m_aURL );
569 aURL.Append( aElementName );
571 return ::utl::UCBContentHelper::IsFolder( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
574 void SAL_CALL FSStorage::removeElement( const OUString& aElementName )
576 std::unique_lock aGuard( m_aMutex );
578 INetURLObject aURL( m_aURL );
579 aURL.Append( aElementName );
581 if ( !::utl::UCBContentHelper::IsFolder( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) )
582 && !::utl::UCBContentHelper::IsDocument( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) )
583 throw container::NoSuchElementException(); // TODO:
585 ::utl::UCBContentHelper::Kill( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
588 void SAL_CALL FSStorage::renameElement( const OUString& aElementName, const OUString& aNewName )
590 std::unique_lock aGuard( m_aMutex );
592 INetURLObject aOldURL( m_aURL );
593 aOldURL.Append( aElementName );
595 INetURLObject aNewURL( m_aURL );
596 aNewURL.Append( aNewName );
598 if ( !::utl::UCBContentHelper::IsFolder( aOldURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) )
599 && !::utl::UCBContentHelper::IsDocument( aOldURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) )
600 throw container::NoSuchElementException(); // TODO:
602 if ( ::utl::UCBContentHelper::IsFolder( aNewURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) )
603 || ::utl::UCBContentHelper::IsDocument( aNewURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) )
604 throw container::ElementExistException(); // TODO:
608 uno::Reference< ucb::XCommandEnvironment > xDummyEnv;
609 ::ucbhelper::Content aSourceContent( aOldURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), xDummyEnv, comphelper::getProcessComponentContext() );
611 m_aContent.transferContent(aSourceContent, ::ucbhelper::InsertOperation::Move, aNewName,
612 ucb::NameClash::ERROR);
614 catch( embed::InvalidStorageException& )
616 throw;
618 catch( lang::IllegalArgumentException& )
620 throw;
622 catch( container::NoSuchElementException& )
624 throw;
626 catch( container::ElementExistException& )
628 throw;
630 catch( io::IOException& )
632 throw;
634 catch( embed::StorageWrappedTargetException& )
636 throw;
638 catch( uno::RuntimeException& )
640 throw;
642 catch( uno::Exception& )
644 uno::Any aCaught( ::cppu::getCaughtException() );
645 throw embed::StorageWrappedTargetException("Can't copy raw stream",
646 uno::Reference< io::XInputStream >(),
647 aCaught );
651 void SAL_CALL FSStorage::copyElementTo( const OUString& aElementName,
652 const uno::Reference< embed::XStorage >& xDest,
653 const OUString& aNewName )
655 std::unique_lock aGuard( m_aMutex );
657 if ( !xDest.is() )
658 throw uno::RuntimeException();
660 INetURLObject aOwnURL( m_aURL );
661 aOwnURL.Append( aElementName );
663 if ( xDest->hasByName( aNewName ) )
664 throw container::ElementExistException(); // TODO:
668 uno::Reference< ucb::XCommandEnvironment > xDummyEnv;
669 if ( ::utl::UCBContentHelper::IsFolder( aOwnURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) )
671 ::ucbhelper::Content aSourceContent( aOwnURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), xDummyEnv, comphelper::getProcessComponentContext() );
672 uno::Reference< embed::XStorage > xDestSubStor(
673 xDest->openStorageElement( aNewName, embed::ElementModes::READWRITE ),
674 uno::UNO_SET_THROW );
676 CopyContentToStorage_Impl( aSourceContent, xDestSubStor );
678 else if ( ::utl::UCBContentHelper::IsDocument( aOwnURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) )
680 CopyStreamToSubStream( aOwnURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), xDest, aNewName );
682 else
683 throw container::NoSuchElementException(); // TODO:
685 catch( embed::InvalidStorageException& )
687 throw;
689 catch( lang::IllegalArgumentException& )
691 throw;
693 catch( container::NoSuchElementException& )
695 throw;
697 catch( container::ElementExistException& )
699 throw;
701 catch( embed::StorageWrappedTargetException& )
703 throw;
705 catch( io::IOException& )
707 throw;
709 catch( uno::RuntimeException& )
711 throw;
713 catch( uno::Exception& )
715 uno::Any aCaught( ::cppu::getCaughtException() );
716 throw embed::StorageWrappedTargetException("Can't copy raw stream",
717 uno::Reference< io::XInputStream >(),
718 aCaught );
722 void SAL_CALL FSStorage::moveElementTo( const OUString& aElementName,
723 const uno::Reference< embed::XStorage >& xDest,
724 const OUString& aNewName )
726 std::unique_lock aGuard( m_aMutex );
727 copyElementTo( aElementName, xDest, aNewName );
729 INetURLObject aOwnURL( m_aURL );
730 aOwnURL.Append( aElementName );
731 if ( !::utl::UCBContentHelper::Kill( aOwnURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) )
732 throw io::IOException(); // TODO: error handling
735 // XNameAccess
737 uno::Any SAL_CALL FSStorage::getByName( const OUString& aName )
739 std::unique_lock aGuard( m_aMutex );
741 if ( aName.isEmpty() )
742 throw lang::IllegalArgumentException();
744 uno::Any aResult;
747 INetURLObject aURL( m_aURL );
748 aURL.Append( aName );
751 if ( ::utl::UCBContentHelper::IsFolder( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) )
753 aResult <<= openStorageElementImpl( aGuard, aName, embed::ElementModes::READ );
755 else if ( ::utl::UCBContentHelper::IsDocument( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) )
757 aResult <<= openStreamElementImpl( aGuard, aName, embed::ElementModes::READ );
759 else
760 throw container::NoSuchElementException(); // TODO:
762 catch (const container::NoSuchElementException&)
764 throw;
766 catch (const lang::WrappedTargetException&)
768 throw;
770 catch (const uno::RuntimeException&)
772 throw;
774 catch (const uno::Exception&)
776 uno::Any aCaught( ::cppu::getCaughtException() );
777 throw lang::WrappedTargetException( "Can not open element!",
778 static_cast< OWeakObject* >( this ),
779 aCaught );
782 return aResult;
786 uno::Sequence< OUString > SAL_CALL FSStorage::getElementNames()
788 std::unique_lock aGuard( m_aMutex );
790 uno::Sequence< OUString > aResult;
794 uno::Sequence<OUString> aProps { "Title" };
796 sal_Int32 nSize = 0;
797 uno::Reference<sdbc::XResultSet> xResultSet
798 = m_aContent.createCursor(aProps, ::ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS);
799 uno::Reference< sdbc::XRow > xRow( xResultSet, uno::UNO_QUERY );
800 if ( xResultSet.is() )
802 // go through the list
803 while ( xResultSet->next() )
805 OUString aName( xRow->getString( 1 ) );
806 aResult.realloc( ++nSize );
807 aResult.getArray()[nSize-1] = aName;
811 catch( const ucb::InteractiveIOException& r )
813 if ( r.Code == ucb::IOErrorCode_NOT_EXISTING )
814 OSL_FAIL( "The folder does not exist!" );
815 else
817 uno::Any aCaught( ::cppu::getCaughtException() );
818 throw lang::WrappedTargetRuntimeException( "Can not open storage!",
819 static_cast< OWeakObject* >( this ),
820 aCaught );
823 catch (const uno::RuntimeException&)
825 throw;
827 catch (const uno::Exception&)
829 uno::Any aCaught( ::cppu::getCaughtException() );
830 throw lang::WrappedTargetRuntimeException( "Can not open storage!",
831 static_cast< OWeakObject* >( this ),
832 aCaught );
835 return aResult;
838 sal_Bool SAL_CALL FSStorage::hasByName( const OUString& aName )
840 std::unique_lock aGuard( m_aMutex );
842 if ( aName.isEmpty() )
843 throw lang::IllegalArgumentException();
845 INetURLObject aURL( m_aURL );
846 aURL.Append( aName );
848 return ( ::utl::UCBContentHelper::IsFolder( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) )
849 || ::utl::UCBContentHelper::IsDocument( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) );
852 uno::Type SAL_CALL FSStorage::getElementType()
854 // it is a multitype container
855 return uno::Type();
858 sal_Bool SAL_CALL FSStorage::hasElements()
860 std::unique_lock aGuard( m_aMutex );
864 uno::Sequence<OUString> aProps { "TargetURL" };
866 uno::Reference<sdbc::XResultSet> xResultSet
867 = m_aContent.createCursor(aProps, ::ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS);
868 return ( xResultSet.is() && xResultSet->next() );
870 catch (const uno::RuntimeException&)
872 throw;
874 catch (const uno::Exception& ex)
876 css::uno::Any anyEx = cppu::getCaughtException();
877 throw lang::WrappedTargetRuntimeException( ex.Message,
878 nullptr, anyEx );
882 // XDisposable
883 void SAL_CALL FSStorage::dispose()
885 std::unique_lock aGuard( m_aMutex );
886 disposeImpl(aGuard);
889 void FSStorage::disposeImpl(std::unique_lock<std::mutex>& rGuard)
891 if ( m_aListenersContainer.getLength(rGuard) )
893 lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >(this) );
894 m_aListenersContainer.disposeAndClear( rGuard, aSource );
898 void SAL_CALL FSStorage::addEventListener(
899 const uno::Reference< lang::XEventListener >& xListener )
901 std::unique_lock aGuard( m_aMutex );
903 m_aListenersContainer.addInterface( aGuard, xListener );
906 void SAL_CALL FSStorage::removeEventListener(
907 const uno::Reference< lang::XEventListener >& xListener )
909 std::unique_lock aGuard( m_aMutex );
911 m_aListenersContainer.removeInterface( aGuard, xListener );
914 // XPropertySet
916 uno::Reference< beans::XPropertySetInfo > SAL_CALL FSStorage::getPropertySetInfo()
918 //TODO:
919 return uno::Reference< beans::XPropertySetInfo >();
923 void SAL_CALL FSStorage::setPropertyValue( const OUString& aPropertyName, const uno::Any& )
925 if ( aPropertyName == "URL" || aPropertyName == "OpenMode" )
926 throw beans::PropertyVetoException(); // TODO
927 else
928 throw beans::UnknownPropertyException(aPropertyName); // TODO
932 uno::Any SAL_CALL FSStorage::getPropertyValue( const OUString& aPropertyName )
934 std::unique_lock aGuard( m_aMutex );
936 if ( aPropertyName == "URL" )
937 return uno::Any( m_aURL );
938 else if ( aPropertyName == "OpenMode" )
939 return uno::Any( m_nMode );
941 throw beans::UnknownPropertyException(aPropertyName); // TODO
945 void SAL_CALL FSStorage::addPropertyChangeListener(
946 const OUString& /*aPropertyName*/,
947 const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/ )
949 //TODO:
953 void SAL_CALL FSStorage::removePropertyChangeListener(
954 const OUString& /*aPropertyName*/,
955 const uno::Reference< beans::XPropertyChangeListener >& /*aListener*/ )
957 //TODO:
961 void SAL_CALL FSStorage::addVetoableChangeListener(
962 const OUString& /*PropertyName*/,
963 const uno::Reference< beans::XVetoableChangeListener >& /*aListener*/ )
965 //TODO:
969 void SAL_CALL FSStorage::removeVetoableChangeListener(
970 const OUString& /*PropertyName*/,
971 const uno::Reference< beans::XVetoableChangeListener >& /*aListener*/ )
973 //TODO:
976 // XHierarchicalStorageAccess
977 uno::Reference< embed::XExtendedStorageStream > SAL_CALL FSStorage::openStreamElementByHierarchicalName( const OUString& sStreamPath, ::sal_Int32 nOpenMode )
979 std::unique_lock aGuard( m_aMutex );
981 if ( sStreamPath.toChar() == '/' )
982 throw lang::IllegalArgumentException();
984 INetURLObject aBaseURL( m_aURL );
985 if ( !aBaseURL.setFinalSlash() )
986 throw uno::RuntimeException();
988 OUString aFileURL = INetURLObject::GetAbsURL(
989 aBaseURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ),
990 sStreamPath );
992 if ( ::utl::UCBContentHelper::IsFolder( aFileURL ) )
993 throw io::IOException();
995 if ( ( nOpenMode & embed::ElementModes::NOCREATE )
996 && !::utl::UCBContentHelper::IsDocument( aFileURL ) )
997 throw io::IOException(); // TODO:
999 uno::Reference< ucb::XCommandEnvironment > xDummyEnv; // TODO: provide InteractionHandler if any
1000 uno::Reference< io::XStream > xResult;
1003 if ( nOpenMode & embed::ElementModes::WRITE )
1005 if ( comphelper::isFileUrl( aFileURL ) )
1007 uno::Reference<ucb::XSimpleFileAccess3> xSimpleFileAccess(
1008 ucb::SimpleFileAccess::create( m_xContext ) );
1009 uno::Reference< io::XStream > xStream =
1010 xSimpleFileAccess->openFileReadWrite( aFileURL );
1012 xResult = new OFSStreamContainer(xStream);
1014 else
1016 // TODO: test whether it really works for http and fwp
1017 std::unique_ptr<SvStream> pStream = ::utl::UcbStreamHelper::CreateStream( aFileURL,
1018 StreamMode::STD_WRITE );
1019 if ( pStream && !pStream->GetError() )
1021 uno::Reference< io::XStream > xStream( new ::utl::OStreamWrapper( std::move(pStream) ) );
1022 xResult = new OFSStreamContainer(xStream);
1026 if ( !xResult.is() )
1027 throw io::IOException();
1029 if ( nOpenMode & embed::ElementModes::TRUNCATE )
1031 uno::Reference< io::XTruncate > xTrunc( xResult->getOutputStream(), uno::UNO_QUERY_THROW );
1032 xTrunc->truncate();
1035 else
1037 if ( ( nOpenMode & embed::ElementModes::TRUNCATE )
1038 || !::utl::UCBContentHelper::IsDocument( aFileURL ) )
1039 throw io::IOException(); // TODO: access denied
1041 ::ucbhelper::Content aResultContent( aFileURL, xDummyEnv, comphelper::getProcessComponentContext() );
1042 uno::Reference< io::XInputStream > xInStream = aResultContent.openStream();
1043 xResult = new OFSInputStreamContainer(xInStream);
1046 catch( embed::InvalidStorageException& )
1048 throw;
1050 catch( lang::IllegalArgumentException& )
1052 throw;
1054 catch( packages::WrongPasswordException& )
1056 throw;
1058 catch( embed::StorageWrappedTargetException& )
1060 throw;
1062 catch( io::IOException& )
1064 throw;
1066 catch( uno::RuntimeException& )
1068 throw;
1070 catch( uno::Exception& )
1072 uno::Any aCaught( ::cppu::getCaughtException() );
1073 throw embed::StorageWrappedTargetException("Can't copy raw stream",
1074 uno::Reference< io::XInputStream >(),
1075 aCaught );
1078 return uno::Reference< embed::XExtendedStorageStream >( xResult, uno::UNO_QUERY_THROW );
1081 uno::Reference< embed::XExtendedStorageStream > SAL_CALL FSStorage::openEncryptedStreamElementByHierarchicalName( const OUString& /*sStreamName*/, ::sal_Int32 /*nOpenMode*/, const OUString& /*sPassword*/ )
1083 throw packages::NoEncryptionException();
1086 void SAL_CALL FSStorage::removeStreamElementByHierarchicalName( const OUString& sStreamPath )
1088 std::unique_lock aGuard( m_aMutex );
1090 // TODO/LATER: may need possibility to create folder if it was removed, since the folder can not be locked
1091 INetURLObject aBaseURL( m_aURL );
1092 if ( !aBaseURL.setFinalSlash() )
1093 throw uno::RuntimeException();
1095 OUString aFileURL = INetURLObject::GetAbsURL(
1096 aBaseURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ),
1097 sStreamPath );
1099 if ( !::utl::UCBContentHelper::IsDocument( aFileURL ) )
1101 if ( ::utl::UCBContentHelper::IsFolder( aFileURL ) )
1102 throw lang::IllegalArgumentException();
1103 else
1104 throw container::NoSuchElementException(); // TODO:
1107 if ( !::utl::UCBContentHelper::Kill( aFileURL ) )
1108 throw io::IOException(); // TODO: error handling
1112 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */