bump product version to 6.3.0.0.beta1
[LibreOffice.git] / svl / source / fsstor / fsstorage.cxx
blobebd730d116e935099be1f5b6e155c09b24bd7603
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/beans/PropertyValue.hpp>
21 #include <com/sun/star/embed/ElementModes.hpp>
22 #include <com/sun/star/embed/InvalidStorageException.hpp>
23 #include <com/sun/star/embed/StorageWrappedTargetException.hpp>
24 #include <com/sun/star/embed/XTransactedObject.hpp>
25 #include <com/sun/star/packages/WrongPasswordException.hpp>
26 #include <com/sun/star/ucb/NameClash.hpp>
27 #include <com/sun/star/ucb/XProgressHandler.hpp>
28 #include <com/sun/star/ucb/XContentAccess.hpp>
29 #include <com/sun/star/ucb/SimpleFileAccess.hpp>
31 #include <com/sun/star/ucb/InteractiveIOException.hpp>
32 #include <com/sun/star/ucb/IOErrorCode.hpp>
33 #include <com/sun/star/container/ElementExistException.hpp>
34 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
35 #include <com/sun/star/container/XEnumerationAccess.hpp>
36 #include <com/sun/star/container/XNamed.hpp>
37 #include <com/sun/star/util/XChangesBatch.hpp>
38 #include <com/sun/star/util/XCloneable.hpp>
39 #include <com/sun/star/lang/XUnoTunnel.hpp>
40 #include <com/sun/star/lang/XComponent.hpp>
41 #include <com/sun/star/lang/DisposedException.hpp>
42 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
43 #include <com/sun/star/io/IOException.hpp>
44 #include <com/sun/star/io/XTruncate.hpp>
45 #include <com/sun/star/io/TempFile.hpp>
46 #include <com/sun/star/sdbc/XResultSet.hpp>
47 #include <com/sun/star/sdbc/XRow.hpp>
49 #include <comphelper/fileurl.hxx>
50 #include <comphelper/processfactory.hxx>
51 #include <comphelper/storagehelper.hxx>
52 #include <cppuhelper/queryinterface.hxx>
53 #include <cppuhelper/typeprovider.hxx>
54 #include <cppuhelper/exc_hlp.hxx>
56 #include <tools/urlobj.hxx>
57 #include <unotools/ucbhelper.hxx>
58 #include <unotools/ucbstreamhelper.hxx>
59 #include <unotools/streamwrap.hxx>
60 #include <ucbhelper/content.hxx>
62 #include "fsstorage.hxx"
63 #include "oinputstreamcontainer.hxx"
64 #include "ostreamcontainer.hxx"
66 using namespace ::com::sun::star;
68 struct FSStorage_Impl
70 OUString const m_aURL;
71 ::ucbhelper::Content m_aContent;
72 sal_Int32 const m_nMode;
73 std::unique_ptr<::comphelper::OInterfaceContainerHelper2> m_pListenersContainer; // list of listeners
74 uno::Reference< uno::XComponentContext > m_xContext;
76 FSStorage_Impl( const ::ucbhelper::Content& aContent, sal_Int32 nMode, uno::Reference< uno::XComponentContext > const & xContext )
77 : m_aURL( aContent.getURL() )
78 , m_aContent( aContent )
79 , m_nMode( nMode )
80 , m_xContext( xContext )
82 OSL_ENSURE( !m_aURL.isEmpty(), "The URL must not be empty" );
85 // Copy assignment is forbidden and not implemented.
86 FSStorage_Impl (const FSStorage_Impl &) = delete;
87 FSStorage_Impl & operator= (const FSStorage_Impl &) = delete;
90 FSStorage::FSStorage( const ::ucbhelper::Content& aContent,
91 sal_Int32 nMode,
92 uno::Reference< uno::XComponentContext > const & xContext )
93 : m_pImpl( new FSStorage_Impl( aContent, nMode, xContext ) )
95 // TODO: use properties
96 if ( !xContext.is() )
97 throw uno::RuntimeException();
99 GetContent();
102 FSStorage::~FSStorage()
104 ::osl::MutexGuard aGuard( m_aMutex );
105 osl_atomic_increment(&m_refCount); // to call dispose
106 try {
107 dispose();
109 catch( uno::RuntimeException& )
113 bool FSStorage::MakeFolderNoUI( const OUString& rFolder )
115 INetURLObject aURL( rFolder );
116 OUString aTitle = aURL.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::WithCharset );
117 aURL.removeSegment();
118 ::ucbhelper::Content aParent;
119 ::ucbhelper::Content aResultContent;
121 if ( ::ucbhelper::Content::create( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ),
122 uno::Reference< ucb::XCommandEnvironment >(),
123 comphelper::getProcessComponentContext(),
124 aParent ) )
125 return ::utl::UCBContentHelper::MakeFolder( aParent, aTitle, aResultContent );
127 return false;
130 ucbhelper::Content& FSStorage::GetContent()
132 ::osl::MutexGuard aGuard( m_aMutex );
133 return m_pImpl->m_aContent;
136 void FSStorage::CopyStreamToSubStream( const OUString& aSourceURL,
137 const uno::Reference< embed::XStorage >& xDest,
138 const OUString& aNewEntryName )
140 if ( !xDest.is() )
141 throw uno::RuntimeException();
143 uno::Reference< ucb::XCommandEnvironment > xDummyEnv;
144 ::ucbhelper::Content aSourceContent( aSourceURL, xDummyEnv, comphelper::getProcessComponentContext() );
145 uno::Reference< io::XInputStream > xSourceInput = aSourceContent.openStream();
147 if ( !xSourceInput.is() )
148 throw io::IOException(); // TODO: error handling
150 uno::Reference< io::XStream > xSubStream = xDest->openStreamElement(
151 aNewEntryName,
152 embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
153 if ( !xSubStream.is() )
154 throw uno::RuntimeException();
156 uno::Reference< io::XOutputStream > xDestOutput = xSubStream->getOutputStream();
157 if ( !xDestOutput.is() )
158 throw uno::RuntimeException();
160 ::comphelper::OStorageHelper::CopyInputToOutput( xSourceInput, xDestOutput );
161 xDestOutput->closeOutput();
164 void FSStorage::CopyContentToStorage_Impl(ucbhelper::Content& rContent,
165 const uno::Reference<embed::XStorage>& xDest)
167 // get list of contents of the Content
168 // create cursor for access to children
169 uno::Sequence< OUString > aProps( 2 );
170 OUString* pProps = aProps.getArray();
171 pProps[0] = "TargetURL";
172 pProps[1] = "IsFolder";
176 uno::Reference<sdbc::XResultSet> xResultSet
177 = rContent.createCursor(aProps, ::ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS);
178 uno::Reference< sdbc::XRow > xRow( xResultSet, uno::UNO_QUERY );
179 if ( xResultSet.is() )
181 // go through the list: insert files as streams, insert folders as substorages using recursion
182 while ( xResultSet->next() )
184 OUString aSourceURL( xRow->getString( 1 ) );
185 bool bIsFolder( xRow->getBoolean(2) );
187 // TODO/LATER: not sure whether the entry name must be encoded
188 OUString aNewEntryName( INetURLObject( aSourceURL ).getName( INetURLObject::LAST_SEGMENT,
189 true,
190 INetURLObject::DecodeMechanism::NONE ) );
191 if ( bIsFolder )
193 uno::Reference< embed::XStorage > xSubStorage = xDest->openStorageElement( aNewEntryName,
194 embed::ElementModes::READWRITE );
195 if ( !xSubStorage.is() )
196 throw uno::RuntimeException();
198 uno::Reference< ucb::XCommandEnvironment > xDummyEnv;
199 ::ucbhelper::Content aSourceContent( aSourceURL, xDummyEnv, comphelper::getProcessComponentContext() );
200 CopyContentToStorage_Impl( aSourceContent, xSubStorage );
202 else
204 CopyStreamToSubStream( aSourceURL, xDest, aNewEntryName );
209 uno::Reference< embed::XTransactedObject > xTransact( xDest, uno::UNO_QUERY );
210 if ( xTransact.is() )
211 xTransact->commit();
213 catch( ucb::InteractiveIOException& r )
215 if ( r.Code == ucb::IOErrorCode_NOT_EXISTING )
216 OSL_FAIL( "The folder does not exist!" );
217 else
218 throw;
222 // XInterface
224 uno::Any SAL_CALL FSStorage::queryInterface( const uno::Type& rType )
226 uno::Any aReturn = ::cppu::queryInterface
227 ( rType
228 , static_cast<lang::XTypeProvider*> ( this )
229 , static_cast<embed::XStorage*> ( this )
230 , static_cast<embed::XHierarchicalStorageAccess*> ( this )
231 , static_cast<container::XNameAccess*> ( this )
232 , static_cast<container::XElementAccess*> ( this )
233 , static_cast<lang::XComponent*> ( this )
234 , static_cast<beans::XPropertySet*> ( this ) );
236 if ( aReturn.hasValue() )
237 return aReturn ;
239 return OWeakObject::queryInterface( rType );
242 void SAL_CALL FSStorage::acquire() throw()
244 OWeakObject::acquire();
247 void SAL_CALL FSStorage::release() throw()
249 OWeakObject::release();
252 // XTypeProvider
254 uno::Sequence< uno::Type > SAL_CALL FSStorage::getTypes()
256 static const uno::Sequence<uno::Type> aTypes {
257 cppu::UnoType<lang::XTypeProvider>::get(),
258 cppu::UnoType<embed::XStorage>::get(),
259 cppu::UnoType<embed::XHierarchicalStorageAccess>::get(),
260 cppu::UnoType<beans::XPropertySet>::get() };
261 return aTypes;
264 uno::Sequence< sal_Int8 > SAL_CALL FSStorage::getImplementationId()
266 return css::uno::Sequence<sal_Int8>();
269 // XStorage
271 void SAL_CALL FSStorage::copyToStorage( const uno::Reference< embed::XStorage >& xDest )
273 ::osl::MutexGuard aGuard( m_aMutex );
275 if ( !m_pImpl )
276 throw lang::DisposedException();
278 if ( !xDest.is() || xDest == uno::Reference< uno::XInterface >( static_cast< OWeakObject*> ( this ), uno::UNO_QUERY ) )
279 throw lang::IllegalArgumentException(); // TODO:
283 CopyContentToStorage_Impl( GetContent(), xDest );
285 catch( embed::InvalidStorageException& )
287 throw;
289 catch( lang::IllegalArgumentException& )
291 throw;
293 catch( embed::StorageWrappedTargetException& )
295 throw;
297 catch( io::IOException& )
299 throw;
301 catch( uno::RuntimeException& )
303 throw;
305 catch( uno::Exception& )
307 uno::Any aCaught( ::cppu::getCaughtException() );
308 throw embed::StorageWrappedTargetException("Can't copy raw stream",
309 uno::Reference< io::XInputStream >(),
310 aCaught );
314 uno::Reference< io::XStream > SAL_CALL FSStorage::openStreamElement(
315 const OUString& aStreamName, sal_Int32 nOpenMode )
317 ::osl::MutexGuard aGuard( m_aMutex );
319 if ( !m_pImpl )
320 throw lang::DisposedException();
322 // TODO/LATER: may need possibility to create folder if it was removed, since the folder can not be locked
323 INetURLObject aFileURL( m_pImpl->m_aURL );
324 aFileURL.Append( aStreamName );
326 if ( ::utl::UCBContentHelper::IsFolder( aFileURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) )
327 throw io::IOException();
329 if ( ( nOpenMode & embed::ElementModes::NOCREATE )
330 && !::utl::UCBContentHelper::IsDocument( aFileURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) )
331 throw io::IOException(); // TODO:
333 uno::Reference< ucb::XCommandEnvironment > xDummyEnv; // TODO: provide InteractionHandler if any
334 uno::Reference< io::XStream > xResult;
337 if ( nOpenMode & embed::ElementModes::WRITE )
339 if ( aFileURL.GetProtocol() == INetProtocol::File )
341 uno::Reference<ucb::XSimpleFileAccess3> xSimpleFileAccess(
342 ucb::SimpleFileAccess::create( m_pImpl->m_xContext ) );
343 xResult = xSimpleFileAccess->openFileReadWrite( aFileURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
345 else
347 // TODO: test whether it really works for http and fwp
348 std::unique_ptr<SvStream> pStream = ::utl::UcbStreamHelper::CreateStream( aFileURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ),
349 StreamMode::STD_WRITE );
350 if ( pStream && !pStream->GetError() )
351 xResult.set( new ::utl::OStreamWrapper( std::move(pStream) ) );
354 if ( !xResult.is() )
355 throw io::IOException();
357 if ( nOpenMode & embed::ElementModes::TRUNCATE )
359 uno::Reference< io::XTruncate > xTrunc( xResult->getOutputStream(), uno::UNO_QUERY_THROW );
360 xTrunc->truncate();
363 else
365 if ( ( nOpenMode & embed::ElementModes::TRUNCATE )
366 || !::utl::UCBContentHelper::IsDocument( aFileURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) )
367 throw io::IOException(); // TODO: access denied
369 ::ucbhelper::Content aResultContent( aFileURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), xDummyEnv, comphelper::getProcessComponentContext() );
370 uno::Reference< io::XInputStream > xInStream = aResultContent.openStream();
371 xResult = new OFSInputStreamContainer(xInStream);
374 catch( embed::InvalidStorageException& )
376 throw;
378 catch( lang::IllegalArgumentException& )
380 throw;
382 catch( packages::WrongPasswordException& )
384 throw;
386 catch( embed::StorageWrappedTargetException& )
388 throw;
390 catch( io::IOException& )
392 throw;
394 catch( uno::RuntimeException& )
396 throw;
398 catch( uno::Exception& )
400 uno::Any aCaught( ::cppu::getCaughtException() );
401 throw embed::StorageWrappedTargetException("Can't copy raw stream",
402 uno::Reference< io::XInputStream >(),
403 aCaught );
406 return xResult;
409 uno::Reference< io::XStream > SAL_CALL FSStorage::openEncryptedStreamElement(
410 const OUString&, sal_Int32, const OUString& )
412 throw packages::NoEncryptionException();
415 uno::Reference< embed::XStorage > SAL_CALL FSStorage::openStorageElement(
416 const OUString& aStorName, sal_Int32 nStorageMode )
418 ::osl::MutexGuard aGuard( m_aMutex );
420 if ( !m_pImpl )
421 throw lang::DisposedException();
423 if ( ( nStorageMode & embed::ElementModes::WRITE )
424 && !( m_pImpl->m_nMode & embed::ElementModes::WRITE ) )
425 throw io::IOException(); // TODO: error handling
427 // TODO/LATER: may need possibility to create folder if it was removed, since the folder can not be locked
428 INetURLObject aFolderURL( m_pImpl->m_aURL );
429 aFolderURL.Append( aStorName );
431 bool bFolderExists = ::utl::UCBContentHelper::IsFolder( aFolderURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
432 if ( !bFolderExists && ::utl::UCBContentHelper::IsDocument( aFolderURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) )
433 throw io::IOException(); // TODO:
435 if ( ( nStorageMode & embed::ElementModes::NOCREATE ) && !bFolderExists )
436 throw io::IOException(); // TODO:
438 uno::Reference< ucb::XCommandEnvironment > xDummyEnv; // TODO: provide InteractionHandler if any
439 uno::Reference< embed::XStorage > xResult;
442 if ( nStorageMode & embed::ElementModes::WRITE )
444 if ( ( nStorageMode & embed::ElementModes::TRUNCATE ) && bFolderExists )
446 ::utl::UCBContentHelper::Kill( aFolderURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
447 bFolderExists =
448 MakeFolderNoUI( aFolderURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); // TODO: not atomic :(
450 else if ( !bFolderExists )
452 bFolderExists =
453 MakeFolderNoUI( aFolderURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); // TODO: not atomic :(
456 else if ( nStorageMode & embed::ElementModes::TRUNCATE )
457 throw io::IOException(); // TODO: access denied
459 if ( !bFolderExists )
460 throw io::IOException(); // there is no such folder
462 ::ucbhelper::Content aResultContent( aFolderURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), xDummyEnv, comphelper::getProcessComponentContext() );
463 xResult.set( static_cast< OWeakObject* >( new FSStorage( aResultContent,
464 nStorageMode,
465 m_pImpl->m_xContext ) ),
466 uno::UNO_QUERY );
468 catch( embed::InvalidStorageException& )
470 throw;
472 catch( lang::IllegalArgumentException& )
474 throw;
476 catch( embed::StorageWrappedTargetException& )
478 throw;
480 catch( io::IOException& )
482 throw;
484 catch( uno::RuntimeException& )
486 throw;
488 catch( uno::Exception& )
490 uno::Any aCaught( ::cppu::getCaughtException() );
491 throw embed::StorageWrappedTargetException("Can't copy raw stream",
492 uno::Reference< io::XInputStream >(),
493 aCaught );
496 return xResult;
499 uno::Reference< io::XStream > SAL_CALL FSStorage::cloneStreamElement( const OUString& aStreamName )
501 ::osl::MutexGuard aGuard( m_aMutex );
503 if ( !m_pImpl )
504 throw lang::DisposedException();
506 // TODO/LATER: may need possibility to create folder if it was removed, since the folder can not be locked
507 INetURLObject aFileURL( m_pImpl->m_aURL );
508 aFileURL.Append( aStreamName );
510 uno::Reference < io::XStream > xTempResult;
513 uno::Reference< ucb::XCommandEnvironment > xDummyEnv;
514 ::ucbhelper::Content aResultContent( aFileURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), xDummyEnv, comphelper::getProcessComponentContext() );
515 uno::Reference< io::XInputStream > xInStream = aResultContent.openStream();
517 xTempResult = io::TempFile::create(m_pImpl->m_xContext);
518 uno::Reference < io::XOutputStream > xTempOut = xTempResult->getOutputStream();
519 uno::Reference < io::XInputStream > xTempIn = xTempResult->getInputStream();
521 if ( !xTempOut.is() || !xTempIn.is() )
522 throw io::IOException();
524 ::comphelper::OStorageHelper::CopyInputToOutput( xInStream, xTempOut );
525 xTempOut->closeOutput();
527 catch( embed::InvalidStorageException& )
529 throw;
531 catch( lang::IllegalArgumentException& )
533 throw;
535 catch( packages::WrongPasswordException& )
537 throw;
539 catch( io::IOException& )
541 throw;
543 catch( embed::StorageWrappedTargetException& )
545 throw;
547 catch( uno::RuntimeException& )
549 throw;
551 catch( uno::Exception& )
553 uno::Any aCaught( ::cppu::getCaughtException() );
554 throw embed::StorageWrappedTargetException("Can't copy raw stream",
555 uno::Reference< io::XInputStream >(),
556 aCaught );
559 return xTempResult;
562 uno::Reference< io::XStream > SAL_CALL FSStorage::cloneEncryptedStreamElement(
563 const OUString&,
564 const OUString& )
566 throw packages::NoEncryptionException();
569 void SAL_CALL FSStorage::copyLastCommitTo(
570 const uno::Reference< embed::XStorage >& xTargetStorage )
572 copyToStorage( xTargetStorage );
575 void SAL_CALL FSStorage::copyStorageElementLastCommitTo(
576 const OUString& aStorName,
577 const uno::Reference< embed::XStorage >& xTargetStorage )
579 ::osl::MutexGuard aGuard( m_aMutex );
581 if ( !m_pImpl )
582 throw lang::DisposedException();
584 uno::Reference< embed::XStorage > xSourceStor( openStorageElement( aStorName, embed::ElementModes::READ ),
585 uno::UNO_SET_THROW );
586 xSourceStor->copyToStorage( xTargetStorage );
589 sal_Bool SAL_CALL FSStorage::isStreamElement( const OUString& aElementName )
591 ::osl::MutexGuard aGuard( m_aMutex );
593 if ( !m_pImpl )
594 throw lang::DisposedException();
596 INetURLObject aURL( m_pImpl->m_aURL );
597 aURL.Append( aElementName );
599 return !::utl::UCBContentHelper::IsFolder( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
602 sal_Bool SAL_CALL FSStorage::isStorageElement( const OUString& aElementName )
604 ::osl::MutexGuard aGuard( m_aMutex );
606 if ( !m_pImpl )
607 throw lang::DisposedException();
609 INetURLObject aURL( m_pImpl->m_aURL );
610 aURL.Append( aElementName );
612 return ::utl::UCBContentHelper::IsFolder( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
615 void SAL_CALL FSStorage::removeElement( const OUString& aElementName )
617 ::osl::MutexGuard aGuard( m_aMutex );
619 if ( !m_pImpl )
620 throw lang::DisposedException();
622 INetURLObject aURL( m_pImpl->m_aURL );
623 aURL.Append( aElementName );
625 if ( !::utl::UCBContentHelper::IsFolder( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) )
626 && !::utl::UCBContentHelper::IsDocument( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) )
627 throw container::NoSuchElementException(); // TODO:
629 ::utl::UCBContentHelper::Kill( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
632 void SAL_CALL FSStorage::renameElement( const OUString& aElementName, const OUString& aNewName )
634 ::osl::MutexGuard aGuard( m_aMutex );
636 if ( !m_pImpl )
637 throw lang::DisposedException();
639 INetURLObject aOldURL( m_pImpl->m_aURL );
640 aOldURL.Append( aElementName );
642 INetURLObject aNewURL( m_pImpl->m_aURL );
643 aNewURL.Append( aNewName );
645 if ( !::utl::UCBContentHelper::IsFolder( aOldURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) )
646 && !::utl::UCBContentHelper::IsDocument( aOldURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) )
647 throw container::NoSuchElementException(); // TODO:
649 if ( ::utl::UCBContentHelper::IsFolder( aNewURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) )
650 || ::utl::UCBContentHelper::IsDocument( aNewURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) )
651 throw container::ElementExistException(); // TODO:
655 uno::Reference< ucb::XCommandEnvironment > xDummyEnv;
656 ::ucbhelper::Content aSourceContent( aOldURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), xDummyEnv, comphelper::getProcessComponentContext() );
658 GetContent().transferContent(aSourceContent, ::ucbhelper::InsertOperation::Move, aNewName,
659 ucb::NameClash::ERROR);
661 catch( embed::InvalidStorageException& )
663 throw;
665 catch( lang::IllegalArgumentException& )
667 throw;
669 catch( container::NoSuchElementException& )
671 throw;
673 catch( container::ElementExistException& )
675 throw;
677 catch( io::IOException& )
679 throw;
681 catch( embed::StorageWrappedTargetException& )
683 throw;
685 catch( uno::RuntimeException& )
687 throw;
689 catch( uno::Exception& )
691 uno::Any aCaught( ::cppu::getCaughtException() );
692 throw embed::StorageWrappedTargetException("Can't copy raw stream",
693 uno::Reference< io::XInputStream >(),
694 aCaught );
698 void SAL_CALL FSStorage::copyElementTo( const OUString& aElementName,
699 const uno::Reference< embed::XStorage >& xDest,
700 const OUString& aNewName )
702 ::osl::MutexGuard aGuard( m_aMutex );
704 if ( !m_pImpl )
705 throw lang::DisposedException();
707 if ( !xDest.is() )
708 throw uno::RuntimeException();
710 INetURLObject aOwnURL( m_pImpl->m_aURL );
711 aOwnURL.Append( aElementName );
713 if ( xDest->hasByName( aNewName ) )
714 throw container::ElementExistException(); // TODO:
718 uno::Reference< ucb::XCommandEnvironment > xDummyEnv;
719 if ( ::utl::UCBContentHelper::IsFolder( aOwnURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) )
721 ::ucbhelper::Content aSourceContent( aOwnURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), xDummyEnv, comphelper::getProcessComponentContext() );
722 uno::Reference< embed::XStorage > xDestSubStor(
723 xDest->openStorageElement( aNewName, embed::ElementModes::READWRITE ),
724 uno::UNO_SET_THROW );
726 CopyContentToStorage_Impl( aSourceContent, xDestSubStor );
728 else if ( ::utl::UCBContentHelper::IsDocument( aOwnURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) )
730 CopyStreamToSubStream( aOwnURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), xDest, aNewName );
732 else
733 throw container::NoSuchElementException(); // TODO:
735 catch( embed::InvalidStorageException& )
737 throw;
739 catch( lang::IllegalArgumentException& )
741 throw;
743 catch( container::NoSuchElementException& )
745 throw;
747 catch( container::ElementExistException& )
749 throw;
751 catch( embed::StorageWrappedTargetException& )
753 throw;
755 catch( io::IOException& )
757 throw;
759 catch( uno::RuntimeException& )
761 throw;
763 catch( uno::Exception& )
765 uno::Any aCaught( ::cppu::getCaughtException() );
766 throw embed::StorageWrappedTargetException("Can't copy raw stream",
767 uno::Reference< io::XInputStream >(),
768 aCaught );
772 void SAL_CALL FSStorage::moveElementTo( const OUString& aElementName,
773 const uno::Reference< embed::XStorage >& xDest,
774 const OUString& aNewName )
776 ::osl::MutexGuard aGuard( m_aMutex );
777 copyElementTo( aElementName, xDest, aNewName );
779 INetURLObject aOwnURL( m_pImpl->m_aURL );
780 aOwnURL.Append( aElementName );
781 if ( !::utl::UCBContentHelper::Kill( aOwnURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) )
782 throw io::IOException(); // TODO: error handling
785 // XNameAccess
787 uno::Any SAL_CALL FSStorage::getByName( const OUString& aName )
789 ::osl::MutexGuard aGuard( m_aMutex );
791 if ( !m_pImpl )
792 throw lang::DisposedException();
794 if ( aName.isEmpty() )
795 throw lang::IllegalArgumentException();
797 uno::Any aResult;
800 INetURLObject aURL( m_pImpl->m_aURL );
801 aURL.Append( aName );
804 if ( ::utl::UCBContentHelper::IsFolder( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) )
806 aResult <<= openStorageElement( aName, embed::ElementModes::READ );
808 else if ( ::utl::UCBContentHelper::IsDocument( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) )
810 aResult <<= openStreamElement( aName, embed::ElementModes::READ );
812 else
813 throw container::NoSuchElementException(); // TODO:
815 catch (const container::NoSuchElementException&)
817 throw;
819 catch (const lang::WrappedTargetException&)
821 throw;
823 catch (const uno::RuntimeException&)
825 throw;
827 catch (const uno::Exception&)
829 uno::Any aCaught( ::cppu::getCaughtException() );
830 throw lang::WrappedTargetException( "Can not open element!",
831 static_cast< OWeakObject* >( this ),
832 aCaught );
835 return aResult;
839 uno::Sequence< OUString > SAL_CALL FSStorage::getElementNames()
841 ::osl::MutexGuard aGuard( m_aMutex );
843 if ( !m_pImpl )
844 throw lang::DisposedException();
846 uno::Sequence< OUString > aResult;
850 uno::Sequence<OUString> aProps { "Title" };
852 sal_Int32 nSize = 0;
853 uno::Reference<sdbc::XResultSet> xResultSet
854 = GetContent().createCursor(aProps, ::ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS);
855 uno::Reference< sdbc::XRow > xRow( xResultSet, uno::UNO_QUERY );
856 if ( xResultSet.is() )
858 // go through the list
859 while ( xResultSet->next() )
861 OUString aName( xRow->getString( 1 ) );
862 aResult.realloc( ++nSize );
863 aResult[nSize-1] = aName;
867 catch( const ucb::InteractiveIOException& r )
869 if ( r.Code == ucb::IOErrorCode_NOT_EXISTING )
870 OSL_FAIL( "The folder does not exist!" );
871 else
873 uno::Any aCaught( ::cppu::getCaughtException() );
874 throw lang::WrappedTargetRuntimeException( "Can not open storage!",
875 static_cast< OWeakObject* >( this ),
876 aCaught );
879 catch (const uno::RuntimeException&)
881 throw;
883 catch (const uno::Exception&)
885 uno::Any aCaught( ::cppu::getCaughtException() );
886 throw lang::WrappedTargetRuntimeException( "Can not open storage!",
887 static_cast< OWeakObject* >( this ),
888 aCaught );
891 return aResult;
894 sal_Bool SAL_CALL FSStorage::hasByName( const OUString& aName )
896 ::osl::MutexGuard aGuard( m_aMutex );
898 if ( !m_pImpl )
899 throw lang::DisposedException();
901 if ( aName.isEmpty() )
902 throw lang::IllegalArgumentException();
904 INetURLObject aURL( m_pImpl->m_aURL );
905 aURL.Append( aName );
907 return ( ::utl::UCBContentHelper::IsFolder( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) )
908 || ::utl::UCBContentHelper::IsDocument( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) );
911 uno::Type SAL_CALL FSStorage::getElementType()
913 ::osl::MutexGuard aGuard( m_aMutex );
915 if ( !m_pImpl )
916 throw lang::DisposedException();
918 // it is a multitype container
919 return uno::Type();
922 sal_Bool SAL_CALL FSStorage::hasElements()
924 ::osl::MutexGuard aGuard( m_aMutex );
926 if ( !m_pImpl )
927 throw lang::DisposedException();
931 uno::Sequence<OUString> aProps { "TargetURL" };
933 uno::Reference<sdbc::XResultSet> xResultSet
934 = GetContent().createCursor(aProps, ::ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS);
935 return ( xResultSet.is() && xResultSet->next() );
937 catch (const uno::RuntimeException&)
939 throw;
941 catch (const uno::Exception& ex)
943 css::uno::Any anyEx = cppu::getCaughtException();
944 throw lang::WrappedTargetRuntimeException( ex.Message,
945 nullptr, anyEx );
949 // XDisposable
950 void SAL_CALL FSStorage::dispose()
952 ::osl::MutexGuard aGuard( m_aMutex );
954 if ( !m_pImpl )
955 throw lang::DisposedException();
957 if ( m_pImpl->m_pListenersContainer )
959 lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >(this) );
960 m_pImpl->m_pListenersContainer->disposeAndClear( aSource );
963 m_pImpl.reset();
966 void SAL_CALL FSStorage::addEventListener(
967 const uno::Reference< lang::XEventListener >& xListener )
969 ::osl::MutexGuard aGuard( m_aMutex );
971 if ( !m_pImpl )
972 throw lang::DisposedException();
974 if ( !m_pImpl->m_pListenersContainer )
975 m_pImpl->m_pListenersContainer.reset(new ::comphelper::OInterfaceContainerHelper2( m_aMutex ));
977 m_pImpl->m_pListenersContainer->addInterface( xListener );
980 void SAL_CALL FSStorage::removeEventListener(
981 const uno::Reference< lang::XEventListener >& xListener )
983 ::osl::MutexGuard aGuard( m_aMutex );
985 if ( !m_pImpl )
986 throw lang::DisposedException();
988 if ( m_pImpl->m_pListenersContainer )
989 m_pImpl->m_pListenersContainer->removeInterface( xListener );
992 // XPropertySet
994 uno::Reference< beans::XPropertySetInfo > SAL_CALL FSStorage::getPropertySetInfo()
996 ::osl::MutexGuard aGuard( m_aMutex );
998 if ( !m_pImpl )
999 throw lang::DisposedException();
1001 //TODO:
1002 return uno::Reference< beans::XPropertySetInfo >();
1006 void SAL_CALL FSStorage::setPropertyValue( const OUString& aPropertyName, const uno::Any& )
1008 ::osl::MutexGuard aGuard( m_aMutex );
1010 if ( !m_pImpl )
1011 throw lang::DisposedException();
1013 if ( aPropertyName == "URL" || aPropertyName == "OpenMode" )
1014 throw beans::PropertyVetoException(); // TODO
1015 else
1016 throw beans::UnknownPropertyException(); // TODO
1020 uno::Any SAL_CALL FSStorage::getPropertyValue( const OUString& aPropertyName )
1022 ::osl::MutexGuard aGuard( m_aMutex );
1024 if ( !m_pImpl )
1025 throw lang::DisposedException();
1027 if ( aPropertyName == "URL" )
1028 return uno::makeAny( m_pImpl->m_aURL );
1029 else if ( aPropertyName == "OpenMode" )
1030 return uno::makeAny( m_pImpl->m_nMode );
1032 throw beans::UnknownPropertyException(); // TODO
1036 void SAL_CALL FSStorage::addPropertyChangeListener(
1037 const OUString& /*aPropertyName*/,
1038 const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/ )
1040 ::osl::MutexGuard aGuard( m_aMutex );
1042 if ( !m_pImpl )
1043 throw lang::DisposedException();
1045 //TODO:
1049 void SAL_CALL FSStorage::removePropertyChangeListener(
1050 const OUString& /*aPropertyName*/,
1051 const uno::Reference< beans::XPropertyChangeListener >& /*aListener*/ )
1053 ::osl::MutexGuard aGuard( m_aMutex );
1055 if ( !m_pImpl )
1056 throw lang::DisposedException();
1058 //TODO:
1062 void SAL_CALL FSStorage::addVetoableChangeListener(
1063 const OUString& /*PropertyName*/,
1064 const uno::Reference< beans::XVetoableChangeListener >& /*aListener*/ )
1066 ::osl::MutexGuard aGuard( m_aMutex );
1068 if ( !m_pImpl )
1069 throw lang::DisposedException();
1071 //TODO:
1075 void SAL_CALL FSStorage::removeVetoableChangeListener(
1076 const OUString& /*PropertyName*/,
1077 const uno::Reference< beans::XVetoableChangeListener >& /*aListener*/ )
1079 ::osl::MutexGuard aGuard( m_aMutex );
1081 if ( !m_pImpl )
1082 throw lang::DisposedException();
1084 //TODO:
1087 // XHierarchicalStorageAccess
1088 uno::Reference< embed::XExtendedStorageStream > SAL_CALL FSStorage::openStreamElementByHierarchicalName( const OUString& sStreamPath, ::sal_Int32 nOpenMode )
1090 ::osl::MutexGuard aGuard( m_aMutex );
1092 if ( !m_pImpl )
1093 throw lang::DisposedException();
1095 if ( sStreamPath.toChar() == '/' )
1096 throw lang::IllegalArgumentException();
1098 INetURLObject aBaseURL( m_pImpl->m_aURL );
1099 if ( !aBaseURL.setFinalSlash() )
1100 throw uno::RuntimeException();
1102 OUString aFileURL = INetURLObject::GetAbsURL(
1103 aBaseURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ),
1104 sStreamPath );
1106 if ( ::utl::UCBContentHelper::IsFolder( aFileURL ) )
1107 throw io::IOException();
1109 if ( ( nOpenMode & embed::ElementModes::NOCREATE )
1110 && !::utl::UCBContentHelper::IsDocument( aFileURL ) )
1111 throw io::IOException(); // TODO:
1113 uno::Reference< ucb::XCommandEnvironment > xDummyEnv; // TODO: provide InteractionHandler if any
1114 uno::Reference< io::XStream > xResult;
1117 if ( nOpenMode & embed::ElementModes::WRITE )
1119 if ( comphelper::isFileUrl( aFileURL ) )
1121 uno::Reference<ucb::XSimpleFileAccess3> xSimpleFileAccess(
1122 ucb::SimpleFileAccess::create( m_pImpl->m_xContext ) );
1123 uno::Reference< io::XStream > xStream =
1124 xSimpleFileAccess->openFileReadWrite( aFileURL );
1126 xResult = new OFSStreamContainer(xStream);
1128 else
1130 // TODO: test whether it really works for http and fwp
1131 std::unique_ptr<SvStream> pStream = ::utl::UcbStreamHelper::CreateStream( aFileURL,
1132 StreamMode::STD_WRITE );
1133 if ( pStream && !pStream->GetError() )
1135 uno::Reference< io::XStream > xStream( new ::utl::OStreamWrapper( std::move(pStream) ) );
1136 xResult = new OFSStreamContainer(xStream);
1140 if ( !xResult.is() )
1141 throw io::IOException();
1143 if ( nOpenMode & embed::ElementModes::TRUNCATE )
1145 uno::Reference< io::XTruncate > xTrunc( xResult->getOutputStream(), uno::UNO_QUERY_THROW );
1146 xTrunc->truncate();
1149 else
1151 if ( ( nOpenMode & embed::ElementModes::TRUNCATE )
1152 || !::utl::UCBContentHelper::IsDocument( aFileURL ) )
1153 throw io::IOException(); // TODO: access denied
1155 ::ucbhelper::Content aResultContent( aFileURL, xDummyEnv, comphelper::getProcessComponentContext() );
1156 uno::Reference< io::XInputStream > xInStream = aResultContent.openStream();
1157 xResult = new OFSInputStreamContainer(xInStream);
1160 catch( embed::InvalidStorageException& )
1162 throw;
1164 catch( lang::IllegalArgumentException& )
1166 throw;
1168 catch( packages::WrongPasswordException& )
1170 throw;
1172 catch( embed::StorageWrappedTargetException& )
1174 throw;
1176 catch( io::IOException& )
1178 throw;
1180 catch( uno::RuntimeException& )
1182 throw;
1184 catch( uno::Exception& )
1186 uno::Any aCaught( ::cppu::getCaughtException() );
1187 throw embed::StorageWrappedTargetException("Can't copy raw stream",
1188 uno::Reference< io::XInputStream >(),
1189 aCaught );
1192 return uno::Reference< embed::XExtendedStorageStream >( xResult, uno::UNO_QUERY_THROW );
1195 uno::Reference< embed::XExtendedStorageStream > SAL_CALL FSStorage::openEncryptedStreamElementByHierarchicalName( const OUString& /*sStreamName*/, ::sal_Int32 /*nOpenMode*/, const OUString& /*sPassword*/ )
1197 throw packages::NoEncryptionException();
1200 void SAL_CALL FSStorage::removeStreamElementByHierarchicalName( const OUString& sStreamPath )
1202 ::osl::MutexGuard aGuard( m_aMutex );
1204 if ( !m_pImpl )
1205 throw lang::DisposedException();
1207 // TODO/LATER: may need possibility to create folder if it was removed, since the folder can not be locked
1208 INetURLObject aBaseURL( m_pImpl->m_aURL );
1209 if ( !aBaseURL.setFinalSlash() )
1210 throw uno::RuntimeException();
1212 OUString aFileURL = INetURLObject::GetAbsURL(
1213 aBaseURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ),
1214 sStreamPath );
1216 if ( !::utl::UCBContentHelper::IsDocument( aFileURL ) )
1218 if ( ::utl::UCBContentHelper::IsFolder( aFileURL ) )
1219 throw lang::IllegalArgumentException();
1220 else
1221 throw container::NoSuchElementException(); // TODO:
1224 if ( !::utl::UCBContentHelper::Kill( aFileURL ) )
1225 throw io::IOException(); // TODO: error handling
1229 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */