bump product version to 7.2.5.1
[LibreOffice.git] / ucb / source / ucp / package / pkgcontent.cxx
blob346a5781050d2f4660cda8abb7a939b4c99f0cd1
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 .
21 /**************************************************************************
22 TODO
23 **************************************************************************
24 *************************************************************************/
25 #include <osl/diagnose.h>
27 #include <rtl/ustring.hxx>
28 #include <com/sun/star/beans/IllegalTypeException.hpp>
29 #include <com/sun/star/beans/PropertyAttribute.hpp>
30 #include <com/sun/star/beans/PropertyExistException.hpp>
31 #include <com/sun/star/beans/PropertyState.hpp>
32 #include <com/sun/star/container/XEnumerationAccess.hpp>
33 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
34 #include <com/sun/star/container/XNameContainer.hpp>
35 #include <com/sun/star/container/XNamed.hpp>
36 #include <com/sun/star/io/BufferSizeExceededException.hpp>
37 #include <com/sun/star/io/NotConnectedException.hpp>
38 #include <com/sun/star/io/XActiveDataSink.hpp>
39 #include <com/sun/star/io/XOutputStream.hpp>
40 #include <com/sun/star/lang/IllegalAccessException.hpp>
41 #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
42 #include <com/sun/star/ucb/IllegalIdentifierException.hpp>
43 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
44 #include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp>
45 #include <com/sun/star/ucb/MissingInputStreamException.hpp>
46 #include <com/sun/star/ucb/NameClash.hpp>
47 #include <com/sun/star/ucb/NameClashException.hpp>
48 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
49 #include <com/sun/star/ucb/OpenMode.hpp>
50 #include <com/sun/star/ucb/TransferInfo.hpp>
51 #include <com/sun/star/ucb/UnsupportedCommandException.hpp>
52 #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
53 #include <com/sun/star/ucb/UnsupportedNameClashException.hpp>
54 #include <com/sun/star/ucb/UnsupportedOpenModeException.hpp>
55 #include <com/sun/star/ucb/XCommandInfo.hpp>
56 #include <com/sun/star/ucb/XPersistentPropertySet.hpp>
57 #include <com/sun/star/util/XChangesBatch.hpp>
58 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
59 #include <com/sun/star/uno/Any.hxx>
60 #include <com/sun/star/uno/Sequence.hxx>
61 #include <comphelper/propertysequence.hxx>
62 #include <cppuhelper/queryinterface.hxx>
63 #include <ucbhelper/contentidentifier.hxx>
64 #include <ucbhelper/propertyvalueset.hxx>
65 #include <ucbhelper/cancelcommandexecution.hxx>
66 #include <ucbhelper/macros.hxx>
67 #include "pkgcontent.hxx"
68 #include "pkgprovider.hxx"
69 #include "pkgresultset.hxx"
71 #include "../inc/urihelper.hxx"
73 using namespace com::sun::star;
74 using namespace package_ucp;
76 #define NONE_MODIFIED sal_uInt32( 0x00 )
77 #define MEDIATYPE_MODIFIED sal_uInt32( 0x01 )
78 #define COMPRESSED_MODIFIED sal_uInt32( 0x02 )
79 #define ENCRYPTED_MODIFIED sal_uInt32( 0x04 )
80 #define ENCRYPTIONKEY_MODIFIED sal_uInt32( 0x08 )
83 // ContentProperties Implementation.
86 ContentProperties::ContentProperties( const OUString& rContentType )
87 : aContentType( rContentType ),
88 nSize( 0 ),
89 bCompressed( true ),
90 bEncrypted( false ),
91 bHasEncryptedEntries( false )
93 bIsFolder = rContentType == PACKAGE_FOLDER_CONTENT_TYPE || rContentType == PACKAGE_ZIP_FOLDER_CONTENT_TYPE;
94 bIsDocument = !bIsFolder;
96 OSL_ENSURE( bIsFolder || rContentType == PACKAGE_STREAM_CONTENT_TYPE || rContentType == PACKAGE_ZIP_STREAM_CONTENT_TYPE,
97 "ContentProperties::ContentProperties - Unknown type!" );
101 uno::Sequence< ucb::ContentInfo >
102 ContentProperties::getCreatableContentsInfo( PackageUri const & rUri ) const
104 if ( bIsFolder )
106 uno::Sequence< beans::Property > aProps( 1 );
107 aProps.getArray()[ 0 ] = beans::Property(
108 "Title",
110 cppu::UnoType<OUString>::get(),
111 beans::PropertyAttribute::BOUND );
113 uno::Sequence< ucb::ContentInfo > aSeq( 2 );
115 // Folder.
116 aSeq.getArray()[ 0 ].Type
117 = Content::getContentType( rUri.getScheme(), true );
118 aSeq.getArray()[ 0 ].Attributes
119 = ucb::ContentInfoAttribute::KIND_FOLDER;
120 aSeq.getArray()[ 0 ].Properties = aProps;
122 // Stream.
123 aSeq.getArray()[ 1 ].Type
124 = Content::getContentType( rUri.getScheme(), false );
125 aSeq.getArray()[ 1 ].Attributes
126 = ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM
127 | ucb::ContentInfoAttribute::KIND_DOCUMENT;
128 aSeq.getArray()[ 1 ].Properties = aProps;
130 return aSeq;
132 else
134 return uno::Sequence< ucb::ContentInfo >( 0 );
139 // Content Implementation.
142 // static ( "virtual" ctor )
143 rtl::Reference<Content> Content::create(
144 const uno::Reference< uno::XComponentContext >& rxContext,
145 ContentProvider* pProvider,
146 const uno::Reference< ucb::XContentIdentifier >& Identifier )
148 OUString aURL = Identifier->getContentIdentifier();
149 PackageUri aURI( aURL );
150 ContentProperties aProps;
151 uno::Reference< container::XHierarchicalNameAccess > xPackage;
153 if ( loadData( pProvider, aURI, aProps, xPackage ) )
155 // resource exists
157 sal_Int32 nLastSlash = aURL.lastIndexOf( '/' );
158 if ( ( nLastSlash + 1 ) == aURL.getLength() )
160 // Client explicitly requested a folder!
161 if ( !aProps.bIsFolder )
162 return nullptr;
165 uno::Reference< ucb::XContentIdentifier > xId
166 = new ::ucbhelper::ContentIdentifier( aURI.getUri() );
167 return new Content( rxContext, pProvider, xId, xPackage, aURI, aProps );
169 else
171 // resource doesn't exist
173 bool bFolder = false;
175 // Guess type according to URI.
176 sal_Int32 nLastSlash = aURL.lastIndexOf( '/' );
177 if ( ( nLastSlash + 1 ) == aURL.getLength() )
178 bFolder = true;
180 uno::Reference< ucb::XContentIdentifier > xId
181 = new ::ucbhelper::ContentIdentifier( aURI.getUri() );
183 ucb::ContentInfo aInfo;
184 if ( bFolder || aURI.isRootFolder() )
185 aInfo.Type = getContentType( aURI.getScheme(), true );
186 else
187 aInfo.Type = getContentType( aURI.getScheme(), false );
189 return new Content( rxContext, pProvider, xId, xPackage, aURI, aInfo );
194 // static ( "virtual" ctor )
195 rtl::Reference<Content> Content::create(
196 const uno::Reference< uno::XComponentContext >& rxContext,
197 ContentProvider* pProvider,
198 const uno::Reference< ucb::XContentIdentifier >& Identifier,
199 const ucb::ContentInfo& Info )
201 if ( Info.Type.isEmpty() )
202 return nullptr;
204 PackageUri aURI( Identifier->getContentIdentifier() );
206 if ( !Info.Type.equalsIgnoreAsciiCase(
207 getContentType( aURI.getScheme(), true ) ) &&
208 !Info.Type.equalsIgnoreAsciiCase(
209 getContentType( aURI.getScheme(), false ) ) )
210 return nullptr;
212 uno::Reference< container::XHierarchicalNameAccess > xPackage = pProvider->createPackage( aURI );
214 uno::Reference< ucb::XContentIdentifier > xId
215 = new ::ucbhelper::ContentIdentifier( aURI.getUri() );
216 return new Content( rxContext, pProvider, xId, xPackage, aURI, Info );
220 // static
221 OUString Content::getContentType(
222 std::u16string_view aScheme, bool bFolder )
224 return ( OUString::Concat("application/")
225 + aScheme
226 + ( bFolder
227 ? OUStringLiteral(u"-folder")
228 : OUStringLiteral(u"-stream") ) );
232 Content::Content(
233 const uno::Reference< uno::XComponentContext >& rxContext,
234 ContentProvider* pProvider,
235 const uno::Reference< ucb::XContentIdentifier >& Identifier,
236 const uno::Reference< container::XHierarchicalNameAccess > & Package,
237 const PackageUri& rUri,
238 const ContentProperties& rProps )
239 : ContentImplHelper( rxContext, pProvider, Identifier ),
240 m_aUri( rUri ),
241 m_aProps( rProps ),
242 m_eState( PERSISTENT ),
243 m_xPackage( Package ),
244 m_pProvider( pProvider ),
245 m_nModifiedProps( NONE_MODIFIED )
250 Content::Content(
251 const uno::Reference< uno::XComponentContext >& rxContext,
252 ContentProvider* pProvider,
253 const uno::Reference< ucb::XContentIdentifier >& Identifier,
254 const uno::Reference< container::XHierarchicalNameAccess > & Package,
255 const PackageUri& rUri,
256 const ucb::ContentInfo& Info )
257 : ContentImplHelper( rxContext, pProvider, Identifier ),
258 m_aUri( rUri ),
259 m_aProps( Info.Type ),
260 m_eState( TRANSIENT ),
261 m_xPackage( Package ),
262 m_pProvider( pProvider ),
263 m_nModifiedProps( NONE_MODIFIED )
268 // virtual
269 Content::~Content()
274 // XInterface methods.
277 // virtual
278 void SAL_CALL Content::acquire()
279 noexcept
281 ContentImplHelper::acquire();
285 // virtual
286 void SAL_CALL Content::release()
287 noexcept
289 ContentImplHelper::release();
293 // virtual
294 uno::Any SAL_CALL Content::queryInterface( const uno::Type & rType )
296 uno::Any aRet;
298 if ( isFolder() )
299 aRet = cppu::queryInterface(
300 rType, static_cast< ucb::XContentCreator * >( this ) );
302 return aRet.hasValue() ? aRet : ContentImplHelper::queryInterface( rType );
306 // XTypeProvider methods.
309 XTYPEPROVIDER_COMMON_IMPL( Content );
312 // virtual
313 uno::Sequence< uno::Type > SAL_CALL Content::getTypes()
315 if ( isFolder() )
317 static cppu::OTypeCollection s_aFolderTypes(
318 CPPU_TYPE_REF( lang::XTypeProvider ),
319 CPPU_TYPE_REF( lang::XServiceInfo ),
320 CPPU_TYPE_REF( lang::XComponent ),
321 CPPU_TYPE_REF( ucb::XContent ),
322 CPPU_TYPE_REF( ucb::XCommandProcessor ),
323 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
324 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
325 CPPU_TYPE_REF( beans::XPropertyContainer ),
326 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
327 CPPU_TYPE_REF( container::XChild ),
328 CPPU_TYPE_REF( ucb::XContentCreator ) );
330 return s_aFolderTypes.getTypes();
333 else
335 static cppu::OTypeCollection s_aDocumentTypes(
336 CPPU_TYPE_REF( lang::XTypeProvider ),
337 CPPU_TYPE_REF( lang::XServiceInfo ),
338 CPPU_TYPE_REF( lang::XComponent ),
339 CPPU_TYPE_REF( ucb::XContent ),
340 CPPU_TYPE_REF( ucb::XCommandProcessor ),
341 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
342 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
343 CPPU_TYPE_REF( beans::XPropertyContainer ),
344 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
345 CPPU_TYPE_REF( container::XChild ) );
347 return s_aDocumentTypes.getTypes();
352 // XServiceInfo methods.
355 // virtual
356 OUString SAL_CALL Content::getImplementationName()
358 return "com.sun.star.comp.ucb.PackageContent";
362 // virtual
363 uno::Sequence< OUString > SAL_CALL Content::getSupportedServiceNames()
365 return { isFolder()? OUString("com.sun.star.ucb.PackageFolderContent"):OUString("com.sun.star.ucb.PackageStreamContent") } ;
369 // XContent methods.
372 // virtual
373 OUString SAL_CALL Content::getContentType()
375 return m_aProps.aContentType;
379 // XCommandProcessor methods.
382 // virtual
383 uno::Any SAL_CALL Content::execute(
384 const ucb::Command& aCommand,
385 sal_Int32 /*CommandId*/,
386 const uno::Reference< ucb::XCommandEnvironment >& Environment )
388 uno::Any aRet;
390 if ( aCommand.Name == "getPropertyValues" )
393 // getPropertyValues
396 uno::Sequence< beans::Property > Properties;
397 if ( !( aCommand.Argument >>= Properties ) )
399 ucbhelper::cancelCommandExecution(
400 uno::makeAny( lang::IllegalArgumentException(
401 "Wrong argument type!",
402 static_cast< cppu::OWeakObject * >( this ),
403 -1 ) ),
404 Environment );
405 // Unreachable
408 aRet <<= getPropertyValues( Properties );
410 else if ( aCommand.Name == "setPropertyValues" )
413 // setPropertyValues
416 uno::Sequence< beans::PropertyValue > aProperties;
417 if ( !( aCommand.Argument >>= aProperties ) )
419 ucbhelper::cancelCommandExecution(
420 uno::makeAny( lang::IllegalArgumentException(
421 "Wrong argument type!",
422 static_cast< cppu::OWeakObject * >( this ),
423 -1 ) ),
424 Environment );
425 // Unreachable
428 if ( !aProperties.hasElements() )
430 ucbhelper::cancelCommandExecution(
431 uno::makeAny( lang::IllegalArgumentException(
432 "No properties!",
433 static_cast< cppu::OWeakObject * >( this ),
434 -1 ) ),
435 Environment );
436 // Unreachable
439 aRet <<= setPropertyValues( aProperties, Environment );
441 else if ( aCommand.Name == "getPropertySetInfo" )
444 // getPropertySetInfo
447 // Note: Implemented by base class.
448 aRet <<= getPropertySetInfo( Environment );
450 else if ( aCommand.Name == "getCommandInfo" )
453 // getCommandInfo
456 // Note: Implemented by base class.
457 aRet <<= getCommandInfo( Environment );
459 else if ( aCommand.Name == "open" )
462 // open
465 ucb::OpenCommandArgument2 aOpenCommand;
466 if ( !( aCommand.Argument >>= aOpenCommand ) )
468 ucbhelper::cancelCommandExecution(
469 uno::makeAny( lang::IllegalArgumentException(
470 "Wrong argument type!",
471 static_cast< cppu::OWeakObject * >( this ),
472 -1 ) ),
473 Environment );
474 // Unreachable
477 aRet = open( aOpenCommand, Environment );
479 else if ( !m_aUri.isRootFolder() && aCommand.Name == "insert" )
482 // insert
485 ucb::InsertCommandArgument aArg;
486 if ( !( aCommand.Argument >>= aArg ) )
488 ucbhelper::cancelCommandExecution(
489 uno::makeAny( lang::IllegalArgumentException(
490 "Wrong argument type!",
491 static_cast< cppu::OWeakObject * >( this ),
492 -1 ) ),
493 Environment );
494 // Unreachable
497 sal_Int32 nNameClash = aArg.ReplaceExisting
498 ? ucb::NameClash::OVERWRITE
499 : ucb::NameClash::ERROR;
500 insert( aArg.Data, nNameClash, Environment );
502 else if ( !m_aUri.isRootFolder() && aCommand.Name == "delete" )
505 // delete
508 bool bDeletePhysical = false;
509 aCommand.Argument >>= bDeletePhysical;
510 destroy( bDeletePhysical, Environment );
512 // Remove own and all children's persistent data.
513 if ( !removeData() )
515 uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence(
517 {"Uri", uno::Any(m_xIdentifier->getContentIdentifier())}
518 }));
519 ucbhelper::cancelCommandExecution(
520 ucb::IOErrorCode_CANT_WRITE,
521 aArgs,
522 Environment,
523 "Cannot remove persistent data!",
524 this );
525 // Unreachable
528 // Remove own and all children's Additional Core Properties.
529 removeAdditionalPropertySet();
531 else if ( aCommand.Name == "transfer" )
534 // transfer
535 // ( Not available at stream objects )
538 ucb::TransferInfo aInfo;
539 if ( !( aCommand.Argument >>= aInfo ) )
541 ucbhelper::cancelCommandExecution(
542 uno::makeAny( lang::IllegalArgumentException(
543 "Wrong argument type!",
544 static_cast< cppu::OWeakObject * >( this ),
545 -1 ) ),
546 Environment );
547 // Unreachable
550 transfer( aInfo, Environment );
552 else if ( aCommand.Name == "createNewContent" && isFolder() )
555 // createNewContent
556 // ( Not available at stream objects )
559 ucb::ContentInfo aInfo;
560 if ( !( aCommand.Argument >>= aInfo ) )
562 OSL_FAIL( "Wrong argument type!" );
563 ucbhelper::cancelCommandExecution(
564 uno::makeAny( lang::IllegalArgumentException(
565 "Wrong argument type!",
566 static_cast< cppu::OWeakObject * >( this ),
567 -1 ) ),
568 Environment );
569 // Unreachable
572 aRet <<= createNewContent( aInfo );
574 else if ( aCommand.Name == "flush" )
577 // flush
578 // ( Not available at stream objects )
581 if( !flushData() )
583 uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence(
585 {"Uri", uno::Any(m_xIdentifier->getContentIdentifier())}
586 }));
587 ucbhelper::cancelCommandExecution(
588 ucb::IOErrorCode_CANT_WRITE,
589 aArgs,
590 Environment,
591 "Cannot write file to disk!",
592 this );
593 // Unreachable
596 else
599 // Unsupported command
602 ucbhelper::cancelCommandExecution(
603 uno::makeAny( ucb::UnsupportedCommandException(
604 OUString(),
605 static_cast< cppu::OWeakObject * >( this ) ) ),
606 Environment );
607 // Unreachable
610 return aRet;
614 // virtual
615 void SAL_CALL Content::abort( sal_Int32 /*CommandId*/ )
617 // @@@ Implement logic to abort running commands, if this makes
618 // sense for your content.
622 // XContentCreator methods.
625 // virtual
626 uno::Sequence< ucb::ContentInfo > SAL_CALL
627 Content::queryCreatableContentsInfo()
629 return m_aProps.getCreatableContentsInfo( m_aUri );
633 // virtual
634 uno::Reference< ucb::XContent > SAL_CALL
635 Content::createNewContent( const ucb::ContentInfo& Info )
637 if ( isFolder() )
639 osl::Guard< osl::Mutex > aGuard( m_aMutex );
641 if ( Info.Type.isEmpty() )
642 return uno::Reference< ucb::XContent >();
644 if ( !Info.Type.equalsIgnoreAsciiCase(
645 getContentType( m_aUri.getScheme(), true ) ) &&
646 !Info.Type.equalsIgnoreAsciiCase(
647 getContentType( m_aUri.getScheme(), false ) ) )
648 return uno::Reference< ucb::XContent >();
650 OUString aURL = m_aUri.getUri() + "/";
652 if ( Info.Type.equalsIgnoreAsciiCase(
653 getContentType( m_aUri.getScheme(), true ) ) )
654 aURL += "New_Folder";
655 else
656 aURL += "New_Stream";
658 uno::Reference< ucb::XContentIdentifier > xId(
659 new ::ucbhelper::ContentIdentifier( aURL ) );
661 return create( m_xContext, m_pProvider, xId, Info );
663 else
665 OSL_FAIL( "createNewContent called on non-folder object!" );
666 return uno::Reference< ucb::XContent >();
671 // Non-interface methods.
674 // virtual
675 OUString Content::getParentURL()
677 return m_aUri.getParentUri();
681 // static
682 uno::Reference< sdbc::XRow > Content::getPropertyValues(
683 const uno::Reference< uno::XComponentContext >& rxContext,
684 const uno::Sequence< beans::Property >& rProperties,
685 ContentProvider* pProvider,
686 const OUString& rContentId )
688 ContentProperties aData;
689 uno::Reference< container::XHierarchicalNameAccess > xPackage;
690 if ( loadData( pProvider, PackageUri( rContentId ), aData, xPackage ) )
692 return getPropertyValues( rxContext,
693 rProperties,
694 aData,
695 rtl::Reference<
696 ::ucbhelper::ContentProviderImplHelper >(
697 pProvider ),
698 rContentId );
700 else
702 rtl::Reference< ::ucbhelper::PropertyValueSet > xRow
703 = new ::ucbhelper::PropertyValueSet( rxContext );
705 for ( const beans::Property& rProp : rProperties )
706 xRow->appendVoid( rProp );
708 return xRow;
713 // static
714 uno::Reference< sdbc::XRow > Content::getPropertyValues(
715 const uno::Reference< uno::XComponentContext >& rxContext,
716 const uno::Sequence< beans::Property >& rProperties,
717 const ContentProperties& rData,
718 const rtl::Reference< ::ucbhelper::ContentProviderImplHelper >&
719 rProvider,
720 const OUString& rContentId )
722 // Note: Empty sequence means "get values of all supported properties".
724 rtl::Reference< ::ucbhelper::PropertyValueSet > xRow
725 = new ::ucbhelper::PropertyValueSet( rxContext );
727 if ( rProperties.hasElements() )
729 uno::Reference< beans::XPropertySet > xAdditionalPropSet;
730 bool bTriedToGetAdditionalPropSet = false;
732 for ( const beans::Property& rProp : rProperties )
734 // Process Core properties.
736 if ( rProp.Name == "ContentType" )
738 xRow->appendString ( rProp, rData.aContentType );
740 else if ( rProp.Name == "Title" )
742 xRow->appendString ( rProp, rData.aTitle );
744 else if ( rProp.Name == "IsDocument" )
746 xRow->appendBoolean( rProp, rData.bIsDocument );
748 else if ( rProp.Name == "IsFolder" )
750 xRow->appendBoolean( rProp, rData.bIsFolder );
752 else if ( rProp.Name == "CreatableContentsInfo" )
754 xRow->appendObject(
755 rProp, uno::makeAny(
756 rData.getCreatableContentsInfo(
757 PackageUri( rContentId ) ) ) );
759 else if ( rProp.Name == "MediaType" )
761 xRow->appendString ( rProp, rData.aMediaType );
763 else if ( rProp.Name == "Size" )
765 // Property only available for streams.
766 if ( rData.bIsDocument )
767 xRow->appendLong( rProp, rData.nSize );
768 else
769 xRow->appendVoid( rProp );
771 else if ( rProp.Name == "Compressed" )
773 // Property only available for streams.
774 if ( rData.bIsDocument )
775 xRow->appendBoolean( rProp, rData.bCompressed );
776 else
777 xRow->appendVoid( rProp );
779 else if ( rProp.Name == "Encrypted" )
781 // Property only available for streams.
782 if ( rData.bIsDocument )
783 xRow->appendBoolean( rProp, rData.bEncrypted );
784 else
785 xRow->appendVoid( rProp );
787 else if ( rProp.Name == "HasEncryptedEntries" )
789 // Property only available for root folder.
790 PackageUri aURI( rContentId );
791 if ( aURI.isRootFolder() )
792 xRow->appendBoolean( rProp, rData.bHasEncryptedEntries );
793 else
794 xRow->appendVoid( rProp );
796 else
798 // Not a Core Property! Maybe it's an Additional Core Property?!
800 if ( !bTriedToGetAdditionalPropSet && !xAdditionalPropSet.is() )
802 xAdditionalPropSet =
803 rProvider->getAdditionalPropertySet( rContentId,
804 false );
805 bTriedToGetAdditionalPropSet = true;
808 if ( xAdditionalPropSet.is() )
810 if ( !xRow->appendPropertySetValue(
811 xAdditionalPropSet,
812 rProp ) )
814 // Append empty entry.
815 xRow->appendVoid( rProp );
818 else
820 // Append empty entry.
821 xRow->appendVoid( rProp );
826 else
828 // Append all Core Properties.
829 xRow->appendString (
830 beans::Property(
831 "ContentType",
833 cppu::UnoType<OUString>::get(),
834 beans::PropertyAttribute::BOUND
835 | beans::PropertyAttribute::READONLY ),
836 rData.aContentType );
837 xRow->appendString(
838 beans::Property(
839 "Title",
841 cppu::UnoType<OUString>::get(),
842 beans::PropertyAttribute::BOUND ),
843 rData.aTitle );
844 xRow->appendBoolean(
845 beans::Property(
846 "IsDocument",
848 cppu::UnoType<bool>::get(),
849 beans::PropertyAttribute::BOUND
850 | beans::PropertyAttribute::READONLY ),
851 rData.bIsDocument );
852 xRow->appendBoolean(
853 beans::Property(
854 "IsFolder",
856 cppu::UnoType<bool>::get(),
857 beans::PropertyAttribute::BOUND
858 | beans::PropertyAttribute::READONLY ),
859 rData.bIsFolder );
860 xRow->appendObject(
861 beans::Property(
862 "CreatableContentsInfo",
864 cppu::UnoType<uno::Sequence< ucb::ContentInfo >>::get(),
865 beans::PropertyAttribute::BOUND
866 | beans::PropertyAttribute::READONLY ),
867 uno::makeAny(
868 rData.getCreatableContentsInfo( PackageUri( rContentId ) ) ) );
869 xRow->appendString(
870 beans::Property(
871 "MediaType",
873 cppu::UnoType<OUString>::get(),
874 beans::PropertyAttribute::BOUND ),
875 rData.aMediaType );
877 // Properties only available for streams.
878 if ( rData.bIsDocument )
880 xRow->appendLong(
881 beans::Property(
882 "Size",
884 cppu::UnoType<sal_Int64>::get(),
885 beans::PropertyAttribute::BOUND
886 | beans::PropertyAttribute::READONLY ),
887 rData.nSize );
889 xRow->appendBoolean(
890 beans::Property(
891 "Compressed",
893 cppu::UnoType<bool>::get(),
894 beans::PropertyAttribute::BOUND ),
895 rData.bCompressed );
897 xRow->appendBoolean(
898 beans::Property(
899 "Encrypted",
901 cppu::UnoType<bool>::get(),
902 beans::PropertyAttribute::BOUND ),
903 rData.bEncrypted );
906 // Properties only available for root folder.
907 PackageUri aURI( rContentId );
908 if ( aURI.isRootFolder() )
910 xRow->appendBoolean(
911 beans::Property(
912 "HasEncryptedEntries",
914 cppu::UnoType<bool>::get(),
915 beans::PropertyAttribute::BOUND
916 | beans::PropertyAttribute::READONLY ),
917 rData.bHasEncryptedEntries );
920 // Append all Additional Core Properties.
922 uno::Reference< beans::XPropertySet > xSet =
923 rProvider->getAdditionalPropertySet( rContentId, false );
924 xRow->appendPropertySet( xSet );
927 return xRow;
931 uno::Reference< sdbc::XRow > Content::getPropertyValues(
932 const uno::Sequence< beans::Property >& rProperties )
934 osl::Guard< osl::Mutex > aGuard( m_aMutex );
935 return getPropertyValues( m_xContext,
936 rProperties,
937 m_aProps,
938 m_xProvider,
939 m_xIdentifier->getContentIdentifier() );
943 uno::Sequence< uno::Any > Content::setPropertyValues(
944 const uno::Sequence< beans::PropertyValue >& rValues,
945 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
947 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
949 uno::Sequence< uno::Any > aRet( rValues.getLength() );
950 uno::Sequence< beans::PropertyChangeEvent > aChanges( rValues.getLength() );
951 sal_Int32 nChanged = 0;
953 beans::PropertyChangeEvent aEvent;
954 aEvent.Source = static_cast< cppu::OWeakObject * >( this );
955 aEvent.Further = false;
956 // aEvent.PropertyName =
957 aEvent.PropertyHandle = -1;
958 // aEvent.OldValue =
959 // aEvent.NewValue =
961 const beans::PropertyValue* pValues = rValues.getConstArray();
962 sal_Int32 nCount = rValues.getLength();
964 uno::Reference< ucb::XPersistentPropertySet > xAdditionalPropSet;
965 bool bTriedToGetAdditionalPropSet = false;
966 bool bExchange = false;
967 bool bStore = false;
968 OUString aNewTitle;
969 sal_Int32 nTitlePos = -1;
971 for ( sal_Int32 n = 0; n < nCount; ++n )
973 const beans::PropertyValue& rValue = pValues[ n ];
975 if ( rValue.Name == "ContentType" )
977 // Read-only property!
978 aRet[ n ] <<= lang::IllegalAccessException(
979 "Property is read-only!",
980 static_cast< cppu::OWeakObject * >( this ) );
982 else if ( rValue.Name == "IsDocument" )
984 // Read-only property!
985 aRet[ n ] <<= lang::IllegalAccessException(
986 "Property is read-only!",
987 static_cast< cppu::OWeakObject * >( this ) );
989 else if ( rValue.Name == "IsFolder" )
991 // Read-only property!
992 aRet[ n ] <<= lang::IllegalAccessException(
993 "Property is read-only!",
994 static_cast< cppu::OWeakObject * >( this ) );
996 else if ( rValue.Name == "CreatableContentsInfo" )
998 // Read-only property!
999 aRet[ n ] <<= lang::IllegalAccessException(
1000 "Property is read-only!",
1001 static_cast< cppu::OWeakObject * >( this ) );
1003 else if ( rValue.Name == "Title" )
1005 if ( m_aUri.isRootFolder() )
1007 // Read-only property!
1008 aRet[ n ] <<= lang::IllegalAccessException(
1009 "Property is read-only!",
1010 static_cast< cppu::OWeakObject * >( this ) );
1012 else
1014 OUString aNewValue;
1015 if ( rValue.Value >>= aNewValue )
1017 // No empty titles!
1018 if ( !aNewValue.isEmpty() )
1020 if ( aNewValue != m_aProps.aTitle )
1022 // modified title -> modified URL -> exchange !
1023 if ( m_eState == PERSISTENT )
1024 bExchange = true;
1026 // new value will be set later...
1027 aNewTitle = aNewValue;
1029 // remember position within sequence of values
1030 // (for error handling).
1031 nTitlePos = n;
1034 else
1036 aRet[ n ] <<=
1037 lang::IllegalArgumentException(
1038 "Empty title not allowed!",
1039 static_cast< cppu::OWeakObject * >( this ),
1040 -1 );
1043 else
1045 aRet[ n ] <<=
1046 beans::IllegalTypeException(
1047 "Property value has wrong type!",
1048 static_cast< cppu::OWeakObject * >( this ) );
1052 else if ( rValue.Name == "MediaType" )
1054 OUString aNewValue;
1055 if ( rValue.Value >>= aNewValue )
1057 if ( aNewValue != m_aProps.aMediaType )
1059 aEvent.PropertyName = rValue.Name;
1060 aEvent.OldValue <<= m_aProps.aMediaType;
1061 aEvent.NewValue <<= aNewValue;
1063 m_aProps.aMediaType = aNewValue;
1064 nChanged++;
1065 bStore = true;
1066 m_nModifiedProps |= MEDIATYPE_MODIFIED;
1069 else
1071 aRet[ n ] <<= beans::IllegalTypeException(
1072 "Property value has wrong type!",
1073 static_cast< cppu::OWeakObject * >( this ) );
1076 else if ( rValue.Name == "Size" )
1078 // Read-only property!
1079 aRet[ n ] <<= lang::IllegalAccessException(
1080 "Property is read-only!",
1081 static_cast< cppu::OWeakObject * >( this ) );
1083 else if ( rValue.Name == "Compressed" )
1085 // Property only available for streams.
1086 if ( m_aProps.bIsDocument )
1088 bool bNewValue;
1089 if ( rValue.Value >>= bNewValue )
1091 if ( bNewValue != m_aProps.bCompressed )
1093 aEvent.PropertyName = rValue.Name;
1094 aEvent.OldValue <<= m_aProps.bCompressed;
1095 aEvent.NewValue <<= bNewValue;
1097 m_aProps.bCompressed = bNewValue;
1098 nChanged++;
1099 bStore = true;
1100 m_nModifiedProps |= COMPRESSED_MODIFIED;
1103 else
1105 aRet[ n ] <<= beans::IllegalTypeException(
1106 "Property value has wrong type!",
1107 static_cast< cppu::OWeakObject * >( this ) );
1110 else
1112 aRet[ n ] <<= beans::UnknownPropertyException(
1113 "Compressed only supported by streams!",
1114 static_cast< cppu::OWeakObject * >( this ) );
1117 else if ( rValue.Name == "Encrypted" )
1119 // Property only available for streams.
1120 if ( m_aProps.bIsDocument )
1122 bool bNewValue;
1123 if ( rValue.Value >>= bNewValue )
1125 if ( bNewValue != m_aProps.bEncrypted )
1127 aEvent.PropertyName = rValue.Name;
1128 aEvent.OldValue <<= m_aProps.bEncrypted;
1129 aEvent.NewValue <<= bNewValue;
1131 m_aProps.bEncrypted = bNewValue;
1132 nChanged++;
1133 bStore = true;
1134 m_nModifiedProps |= ENCRYPTED_MODIFIED;
1137 else
1139 aRet[ n ] <<= beans::IllegalTypeException(
1140 "Property value has wrong type!",
1141 static_cast< cppu::OWeakObject * >( this ) );
1144 else
1146 aRet[ n ] <<= beans::UnknownPropertyException(
1147 "Encrypted only supported by streams!",
1148 static_cast< cppu::OWeakObject * >( this ) );
1151 else if ( rValue.Name == "HasEncryptedEntries" )
1153 // Read-only property!
1154 aRet[ n ] <<= lang::IllegalAccessException(
1155 "Property is read-only!",
1156 static_cast< cppu::OWeakObject * >( this ) );
1158 else if ( rValue.Name == "EncryptionKey" )
1160 // @@@ This is a temporary solution. In the future submitting
1161 // the key should be done using an interaction handler!
1163 // Write-Only property. Only supported by root folder and streams
1164 // (all non-root folders of a package have the same encryption key).
1165 if ( m_aUri.isRootFolder() || m_aProps.bIsDocument )
1167 uno::Sequence < sal_Int8 > aNewValue;
1168 if ( rValue.Value >>= aNewValue )
1170 if ( aNewValue != m_aProps.aEncryptionKey )
1172 aEvent.PropertyName = rValue.Name;
1173 aEvent.OldValue <<= m_aProps.aEncryptionKey;
1174 aEvent.NewValue <<= aNewValue;
1176 m_aProps.aEncryptionKey = aNewValue;
1177 nChanged++;
1178 bStore = true;
1179 m_nModifiedProps |= ENCRYPTIONKEY_MODIFIED;
1182 else
1184 aRet[ n ] <<= beans::IllegalTypeException(
1185 "Property value has wrong type!",
1186 static_cast< cppu::OWeakObject * >( this ) );
1189 else
1191 aRet[ n ] <<= beans::UnknownPropertyException(
1192 "EncryptionKey not supported by non-root folder!",
1193 static_cast< cppu::OWeakObject * >( this ) );
1196 else
1198 // Not a Core Property! Maybe it's an Additional Core Property?!
1200 if ( !bTriedToGetAdditionalPropSet && !xAdditionalPropSet.is() )
1202 xAdditionalPropSet = getAdditionalPropertySet( false );
1203 bTriedToGetAdditionalPropSet = true;
1206 if ( xAdditionalPropSet.is() )
1210 uno::Any aOldValue
1211 = xAdditionalPropSet->getPropertyValue( rValue.Name );
1212 if ( aOldValue != rValue.Value )
1214 xAdditionalPropSet->setPropertyValue(
1215 rValue.Name, rValue.Value );
1217 aEvent.PropertyName = rValue.Name;
1218 aEvent.OldValue = aOldValue;
1219 aEvent.NewValue = rValue.Value;
1221 aChanges.getArray()[ nChanged ] = aEvent;
1222 nChanged++;
1225 catch ( beans::UnknownPropertyException const & e )
1227 aRet[ n ] <<= e;
1229 catch ( lang::WrappedTargetException const & e )
1231 aRet[ n ] <<= e;
1233 catch ( beans::PropertyVetoException const & e )
1235 aRet[ n ] <<= e;
1237 catch ( lang::IllegalArgumentException const & e )
1239 aRet[ n ] <<= e;
1242 else
1244 aRet[ n ] <<= uno::Exception(
1245 "No property set for storing the value!",
1246 static_cast< cppu::OWeakObject * >( this ) );
1251 if ( bExchange )
1253 uno::Reference< ucb::XContentIdentifier > xOldId = m_xIdentifier;
1255 // Assemble new content identifier...
1256 OUString aNewURL = m_aUri.getParentUri() + "/";
1257 aNewURL += ::ucb_impl::urihelper::encodeSegment( aNewTitle );
1258 uno::Reference< ucb::XContentIdentifier > xNewId
1259 = new ::ucbhelper::ContentIdentifier( aNewURL );
1261 aGuard.clear();
1262 if ( exchangeIdentity( xNewId ) )
1264 // Adapt persistent data.
1265 renameData( xOldId, xNewId );
1267 // Adapt Additional Core Properties.
1268 renameAdditionalPropertySet( xOldId->getContentIdentifier(),
1269 xNewId->getContentIdentifier() );
1271 else
1273 // Do not set new title!
1274 aNewTitle.clear();
1276 // Set error .
1277 aRet[ nTitlePos ] <<= uno::Exception(
1278 "Exchange failed!",
1279 static_cast< cppu::OWeakObject * >( this ) );
1283 if ( !aNewTitle.isEmpty() )
1285 aEvent.PropertyName = "Title";
1286 aEvent.OldValue <<= m_aProps.aTitle;
1287 aEvent.NewValue <<= aNewTitle;
1289 m_aProps.aTitle = aNewTitle;
1291 aChanges.getArray()[ nChanged ] = aEvent;
1292 nChanged++;
1295 if ( nChanged > 0 )
1297 // Save changes, if content was already made persistent.
1298 if ( ( m_nModifiedProps & ENCRYPTIONKEY_MODIFIED ) ||
1299 ( bStore && ( m_eState == PERSISTENT ) ) )
1301 if ( !storeData( uno::Reference< io::XInputStream >() ) )
1303 uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence(
1305 {"Uri", uno::Any(m_xIdentifier->getContentIdentifier())}
1306 }));
1307 ucbhelper::cancelCommandExecution(
1308 ucb::IOErrorCode_CANT_WRITE,
1309 aArgs,
1310 xEnv,
1311 "Cannot store persistent data!",
1312 this );
1313 // Unreachable
1317 aGuard.clear();
1318 aChanges.realloc( nChanged );
1319 notifyPropertiesChange( aChanges );
1322 return aRet;
1326 uno::Any Content::open(
1327 const ucb::OpenCommandArgument2& rArg,
1328 const uno::Reference< ucb::XCommandEnvironment >& xEnv )
1330 if ( rArg.Mode == ucb::OpenMode::ALL ||
1331 rArg.Mode == ucb::OpenMode::FOLDERS ||
1332 rArg.Mode == ucb::OpenMode::DOCUMENTS )
1335 // open command for a folder content
1338 uno::Reference< ucb::XDynamicResultSet > xSet
1339 = new DynamicResultSet( m_xContext, this, rArg, xEnv );
1340 return uno::makeAny( xSet );
1342 else
1345 // open command for a document content
1348 if ( ( rArg.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE ) ||
1349 ( rArg.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE ) )
1351 // Currently(?) unsupported.
1352 ucbhelper::cancelCommandExecution(
1353 uno::makeAny( ucb::UnsupportedOpenModeException(
1354 OUString(),
1355 static_cast< cppu::OWeakObject * >( this ),
1356 sal_Int16( rArg.Mode ) ) ),
1357 xEnv );
1358 // Unreachable
1361 uno::Reference< io::XOutputStream > xOut( rArg.Sink, uno::UNO_QUERY );
1362 if ( xOut.is() )
1364 // PUSH: write data into xOut
1366 uno::Reference< io::XInputStream > xIn = getInputStream();
1367 if ( !xIn.is() )
1369 // No interaction if we are not persistent!
1370 uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence(
1372 {"Uri", uno::Any(m_xIdentifier->getContentIdentifier())}
1373 }));
1374 ucbhelper::cancelCommandExecution(
1375 ucb::IOErrorCode_CANT_READ,
1376 aArgs,
1377 m_eState == PERSISTENT
1378 ? xEnv
1379 : uno::Reference< ucb::XCommandEnvironment >(),
1380 "Got no data stream!",
1381 this );
1382 // Unreachable
1387 uno::Sequence< sal_Int8 > aBuffer;
1388 while (true)
1390 sal_Int32 nRead = xIn->readSomeBytes( aBuffer, 65536 );
1391 if (!nRead)
1392 break;
1393 aBuffer.realloc( nRead );
1394 xOut->writeBytes( aBuffer );
1397 xOut->closeOutput();
1399 catch ( io::NotConnectedException const & )
1401 // closeOutput, readSomeBytes, writeBytes
1403 catch ( io::BufferSizeExceededException const & )
1405 // closeOutput, readSomeBytes, writeBytes
1407 catch ( io::IOException const & )
1409 // closeOutput, readSomeBytes, writeBytes
1412 else
1414 uno::Reference< io::XActiveDataSink > xDataSink(
1415 rArg.Sink, uno::UNO_QUERY );
1416 if ( xDataSink.is() )
1418 // PULL: wait for client read
1420 uno::Reference< io::XInputStream > xIn = getInputStream();
1421 if ( !xIn.is() )
1423 // No interaction if we are not persistent!
1424 uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence(
1426 {"Uri", uno::Any(m_xIdentifier->getContentIdentifier())}
1427 }));
1428 ucbhelper::cancelCommandExecution(
1429 ucb::IOErrorCode_CANT_READ,
1430 aArgs,
1431 m_eState == PERSISTENT
1432 ? xEnv
1433 : uno::Reference<
1434 ucb::XCommandEnvironment >(),
1435 "Got no data stream!",
1436 this );
1437 // Unreachable
1440 // Done.
1441 xDataSink->setInputStream( xIn );
1443 else
1445 // Note: aOpenCommand.Sink may contain an XStream
1446 // implementation. Support for this type of
1447 // sink is optional...
1448 ucbhelper::cancelCommandExecution(
1449 uno::makeAny(
1450 ucb::UnsupportedDataSinkException(
1451 OUString(),
1452 static_cast< cppu::OWeakObject * >( this ),
1453 rArg.Sink ) ),
1454 xEnv );
1455 // Unreachable
1460 return uno::Any();
1464 void Content::insert(
1465 const uno::Reference< io::XInputStream >& xStream,
1466 sal_Int32 nNameClashResolve,
1467 const uno::Reference< ucb::XCommandEnvironment >& xEnv )
1469 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1471 // Check, if all required properties were set.
1472 if ( isFolder() )
1474 // Required: Title
1476 if ( m_aProps.aTitle.isEmpty() )
1477 m_aProps.aTitle = m_aUri.getName();
1479 else
1481 // Required: rArg.Data
1483 if ( !xStream.is() )
1485 ucbhelper::cancelCommandExecution(
1486 uno::makeAny( ucb::MissingInputStreamException(
1487 OUString(),
1488 static_cast< cppu::OWeakObject * >( this ) ) ),
1489 xEnv );
1490 // Unreachable
1493 // Required: Title
1495 if ( m_aProps.aTitle.isEmpty() )
1496 m_aProps.aTitle = m_aUri.getName();
1499 OUString aNewURL = m_aUri.getParentUri();
1500 if (1 + aNewURL.lastIndexOf('/') != aNewURL.getLength())
1501 aNewURL += "/";
1502 aNewURL += ::ucb_impl::urihelper::encodeSegment( m_aProps.aTitle );
1503 PackageUri aNewUri( aNewURL );
1505 // Handle possible name clash...
1506 switch ( nNameClashResolve )
1508 // fail.
1509 case ucb::NameClash::ERROR:
1510 if ( hasData( aNewUri ) )
1512 ucbhelper::cancelCommandExecution(
1513 uno::makeAny( ucb::NameClashException(
1514 OUString(),
1515 static_cast< cppu::OWeakObject * >( this ),
1516 task::InteractionClassification_ERROR,
1517 m_aProps.aTitle ) ),
1518 xEnv );
1519 // Unreachable
1521 break;
1523 // replace (possibly) existing object.
1524 case ucb::NameClash::OVERWRITE:
1525 break;
1527 // "invent" a new valid title.
1528 case ucb::NameClash::RENAME:
1529 if ( hasData( aNewUri ) )
1531 sal_Int32 nTry = 0;
1535 OUString aNew = aNewUri.getUri() + "_";
1536 aNew += OUString::number( ++nTry );
1537 aNewUri.setUri( aNew );
1539 while ( hasData( aNewUri ) && ( nTry < 1000 ) );
1541 if ( nTry == 1000 )
1543 ucbhelper::cancelCommandExecution(
1544 uno::makeAny(
1545 ucb::UnsupportedNameClashException(
1546 "Unable to resolve name clash!",
1547 static_cast< cppu::OWeakObject * >( this ),
1548 nNameClashResolve ) ),
1549 xEnv );
1550 // Unreachable
1552 else
1554 m_aProps.aTitle += "_";
1555 m_aProps.aTitle += OUString::number( nTry );
1558 break;
1560 case ucb::NameClash::KEEP: // deprecated
1561 case ucb::NameClash::ASK:
1562 default:
1563 if ( hasData( aNewUri ) )
1565 ucbhelper::cancelCommandExecution(
1566 uno::makeAny(
1567 ucb::UnsupportedNameClashException(
1568 OUString(),
1569 static_cast< cppu::OWeakObject * >( this ),
1570 nNameClashResolve ) ),
1571 xEnv );
1572 // Unreachable
1574 break;
1577 // Identifier changed?
1578 bool bNewId = ( m_aUri.getUri() != aNewUri.getUri() );
1580 if ( bNewId )
1582 m_xIdentifier = new ::ucbhelper::ContentIdentifier( aNewURL );
1583 m_aUri = aNewUri;
1586 if ( !storeData( xStream ) )
1588 uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence(
1590 {"Uri", uno::Any(m_xIdentifier->getContentIdentifier())}
1591 }));
1592 ucbhelper::cancelCommandExecution(
1593 ucb::IOErrorCode_CANT_WRITE,
1594 aArgs,
1595 xEnv,
1596 "Cannot store persistent data!",
1597 this );
1598 // Unreachable
1601 m_eState = PERSISTENT;
1603 if ( bNewId )
1605 // Take over correct default values from underlying packager...
1606 uno::Reference< container::XHierarchicalNameAccess > xXHierarchicalNameAccess;
1607 loadData( m_pProvider,
1608 m_aUri,
1609 m_aProps,
1610 xXHierarchicalNameAccess );
1612 aGuard.clear();
1613 inserted();
1618 void Content::destroy(
1619 bool bDeletePhysical,
1620 const uno::Reference< ucb::XCommandEnvironment >& xEnv )
1622 // @@@ take care about bDeletePhysical -> trashcan support
1624 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1626 uno::Reference< ucb::XContent > xThis = this;
1628 // Persistent?
1629 if ( m_eState != PERSISTENT )
1631 ucbhelper::cancelCommandExecution(
1632 uno::makeAny( ucb::UnsupportedCommandException(
1633 "Not persistent!",
1634 static_cast< cppu::OWeakObject * >( this ) ) ),
1635 xEnv );
1636 // Unreachable
1639 m_eState = DEAD;
1641 aGuard.clear();
1642 deleted();
1644 if ( isFolder() )
1646 // Process instantiated children...
1648 ContentRefList aChildren;
1649 queryChildren( aChildren );
1651 for ( auto& rChild : aChildren )
1653 rChild->destroy( bDeletePhysical, xEnv );
1659 void Content::transfer(
1660 const ucb::TransferInfo& rInfo,
1661 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
1663 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1665 // Persistent?
1666 if ( m_eState != PERSISTENT )
1668 ucbhelper::cancelCommandExecution(
1669 uno::makeAny( ucb::UnsupportedCommandException(
1670 "Not persistent!",
1671 static_cast< cppu::OWeakObject * >( this ) ) ),
1672 xEnv );
1673 // Unreachable
1676 // Is source a package content?
1677 if ( ( rInfo.SourceURL.isEmpty() ) ||
1678 ( rInfo.SourceURL.compareTo(
1679 m_aUri.getUri(), PACKAGE_URL_SCHEME_LENGTH + 3 ) != 0 ) )
1681 ucbhelper::cancelCommandExecution(
1682 uno::makeAny( ucb::InteractiveBadTransferURLException(
1683 OUString(),
1684 static_cast< cppu::OWeakObject * >( this ) ) ),
1685 xEnv );
1686 // Unreachable
1689 // Is source not a parent of me / not me?
1690 OUString aId = m_aUri.getParentUri() + "/";
1692 if ( rInfo.SourceURL.getLength() <= aId.getLength() )
1694 if ( aId.startsWith( rInfo.SourceURL ) )
1696 uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence(
1698 {"Uri", uno::Any(rInfo.SourceURL)}
1699 }));
1700 ucbhelper::cancelCommandExecution(
1701 ucb::IOErrorCode_RECURSIVE,
1702 aArgs,
1703 xEnv,
1704 "Target is equal to or is a child of source!",
1705 this );
1706 // Unreachable
1711 // 0) Obtain content object for source.
1714 uno::Reference< ucb::XContentIdentifier > xId
1715 = new ::ucbhelper::ContentIdentifier( rInfo.SourceURL );
1717 // Note: The static cast is okay here, because its sure that
1718 // m_xProvider is always the PackageContentProvider.
1719 rtl::Reference< Content > xSource;
1723 xSource = static_cast< Content * >(
1724 m_xProvider->queryContent( xId ).get() );
1726 catch ( ucb::IllegalIdentifierException const & )
1728 // queryContent
1731 if ( !xSource.is() )
1733 uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence(
1735 {"Uri", uno::Any(xId->getContentIdentifier())}
1736 }));
1737 ucbhelper::cancelCommandExecution(
1738 ucb::IOErrorCode_CANT_READ,
1739 aArgs,
1740 xEnv,
1741 "Cannot instantiate source object!",
1742 this );
1743 // Unreachable
1747 // 1) Create new child content.
1750 OUString aType = xSource->isFolder()
1751 ? getContentType( m_aUri.getScheme(), true )
1752 : getContentType( m_aUri.getScheme(), false );
1753 ucb::ContentInfo aContentInfo;
1754 aContentInfo.Type = aType;
1755 aContentInfo.Attributes = 0;
1757 // Note: The static cast is okay here, because its sure that
1758 // createNewContent always creates a Content.
1759 rtl::Reference< Content > xTarget
1760 = static_cast< Content * >( createNewContent( aContentInfo ).get() );
1761 if ( !xTarget.is() )
1763 uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence(
1765 {"Folder", uno::Any(aId)}
1766 }));
1767 ucbhelper::cancelCommandExecution(
1768 ucb::IOErrorCode_CANT_CREATE,
1769 aArgs,
1770 xEnv,
1771 "XContentCreator::createNewContent failed!",
1772 this );
1773 // Unreachable
1777 // 2) Copy data from source content to child content.
1780 uno::Sequence< beans::Property > aSourceProps
1781 = xSource->getPropertySetInfo( xEnv )->getProperties();
1782 sal_Int32 nCount = aSourceProps.getLength();
1784 if ( nCount )
1786 bool bHadTitle = rInfo.NewTitle.isEmpty();
1788 // Get all source values.
1789 uno::Reference< sdbc::XRow > xRow
1790 = xSource->getPropertyValues( aSourceProps );
1792 uno::Sequence< beans::PropertyValue > aValues( nCount );
1793 beans::PropertyValue* pValues = aValues.getArray();
1795 const beans::Property* pProps = aSourceProps.getConstArray();
1796 for ( sal_Int32 n = 0; n < nCount; ++n )
1798 const beans::Property& rProp = pProps[ n ];
1799 beans::PropertyValue& rValue = pValues[ n ];
1801 rValue.Name = rProp.Name;
1802 rValue.Handle = rProp.Handle;
1804 if ( !bHadTitle && rProp.Name == "Title" )
1806 // Set new title instead of original.
1807 bHadTitle = true;
1808 rValue.Value <<= rInfo.NewTitle;
1810 else
1811 rValue.Value
1812 = xRow->getObject( n + 1,
1813 uno::Reference<
1814 container::XNameAccess >() );
1816 rValue.State = beans::PropertyState_DIRECT_VALUE;
1818 if ( rProp.Attributes & beans::PropertyAttribute::REMOVABLE )
1820 // Add Additional Core Property.
1823 xTarget->addProperty( rProp.Name,
1824 rProp.Attributes,
1825 rValue.Value );
1827 catch ( beans::PropertyExistException const & )
1830 catch ( beans::IllegalTypeException const & )
1833 catch ( lang::IllegalArgumentException const & )
1839 // Set target values.
1840 xTarget->setPropertyValues( aValues, xEnv );
1844 // 3) Commit (insert) child.
1847 xTarget->insert( xSource->getInputStream(), rInfo.NameClash, xEnv );
1850 // 4) Transfer (copy) children of source.
1853 if ( xSource->isFolder() )
1855 uno::Reference< container::XEnumeration > xIter
1856 = xSource->getIterator();
1857 if ( xIter.is() )
1859 while ( xIter->hasMoreElements() )
1863 uno::Reference< container::XNamed > xNamed;
1864 xIter->nextElement() >>= xNamed;
1866 if ( !xNamed.is() )
1868 OSL_FAIL( "Content::transfer - Got no XNamed!" );
1869 break;
1872 OUString aName = xNamed->getName();
1874 if ( aName.isEmpty() )
1876 OSL_FAIL( "Content::transfer - Empty name!" );
1877 break;
1880 OUString aChildId = xId->getContentIdentifier();
1881 if ( ( aChildId.lastIndexOf( '/' ) + 1 )
1882 != aChildId.getLength() )
1883 aChildId += "/";
1885 aChildId += ::ucb_impl::urihelper::encodeSegment( aName );
1887 ucb::TransferInfo aInfo;
1888 aInfo.MoveData = false;
1889 aInfo.NewTitle.clear();
1890 aInfo.SourceURL = aChildId;
1891 aInfo.NameClash = rInfo.NameClash;
1893 // Transfer child to target.
1894 xTarget->transfer( aInfo, xEnv );
1896 catch ( container::NoSuchElementException const & )
1899 catch ( lang::WrappedTargetException const & )
1907 // 5) Destroy source ( when moving only ) .
1910 if ( !rInfo.MoveData )
1911 return;
1913 xSource->destroy( true, xEnv );
1915 // Remove all persistent data of source and its children.
1916 if ( !xSource->removeData() )
1918 uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence(
1920 {"Uri", uno::Any(xSource->m_xIdentifier->getContentIdentifier())}
1921 }));
1922 ucbhelper::cancelCommandExecution(
1923 ucb::IOErrorCode_CANT_WRITE,
1924 aArgs,
1925 xEnv,
1926 "Cannot remove persistent data of source object!",
1927 this );
1928 // Unreachable
1931 // Remove own and all children's Additional Core Properties.
1932 xSource->removeAdditionalPropertySet();
1936 bool Content::exchangeIdentity(
1937 const uno::Reference< ucb::XContentIdentifier >& xNewId )
1939 if ( !xNewId.is() )
1940 return false;
1942 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1944 uno::Reference< ucb::XContent > xThis = this;
1946 // Already persistent?
1947 if ( m_eState != PERSISTENT )
1949 OSL_FAIL( "Content::exchangeIdentity - Not persistent!" );
1950 return false;
1953 // Exchange own identity.
1955 // Fail, if a content with given id already exists.
1956 PackageUri aNewUri( xNewId->getContentIdentifier() );
1957 if ( !hasData( aNewUri ) )
1959 OUString aOldURL = m_xIdentifier->getContentIdentifier();
1961 aGuard.clear();
1962 if ( exchange( xNewId ) )
1964 m_aUri = aNewUri;
1965 if ( isFolder() )
1967 // Process instantiated children...
1969 ContentRefList aChildren;
1970 queryChildren( aChildren );
1972 for ( const auto& rChild : aChildren )
1974 ContentRef xChild = rChild;
1976 // Create new content identifier for the child...
1977 uno::Reference< ucb::XContentIdentifier > xOldChildId
1978 = xChild->getIdentifier();
1979 OUString aOldChildURL
1980 = xOldChildId->getContentIdentifier();
1981 OUString aNewChildURL
1982 = aOldChildURL.replaceAt(
1984 aOldURL.getLength(),
1985 xNewId->getContentIdentifier() );
1986 uno::Reference< ucb::XContentIdentifier > xNewChildId
1987 = new ::ucbhelper::ContentIdentifier( aNewChildURL );
1989 if ( !xChild->exchangeIdentity( xNewChildId ) )
1990 return false;
1993 return true;
1997 OSL_FAIL( "Content::exchangeIdentity - Panic! Cannot exchange identity!" );
1998 return false;
2002 void Content::queryChildren( ContentRefList& rChildren )
2004 // Obtain a list with a snapshot of all currently instantiated contents
2005 // from provider and extract the contents which are direct children
2006 // of this content.
2008 ::ucbhelper::ContentRefList aAllContents;
2009 m_xProvider->queryExistingContents( aAllContents );
2011 OUString aURL = m_xIdentifier->getContentIdentifier();
2013 OSL_ENSURE( aURL.lastIndexOf( '/' ) != ( aURL.getLength() - 1 ),
2014 "Content::queryChildren - Invalid URL!" );
2016 aURL += "/";
2018 sal_Int32 nLen = aURL.getLength();
2020 for ( const auto& rContent : aAllContents )
2022 ::ucbhelper::ContentImplHelperRef xChild = rContent;
2023 OUString aChildURL
2024 = xChild->getIdentifier()->getContentIdentifier();
2026 // Is aURL a prefix of aChildURL?
2027 if ( ( aChildURL.getLength() > nLen ) &&
2028 ( aChildURL.startsWith( aURL ) ) )
2030 if ( aChildURL.indexOf( '/', nLen ) == -1 )
2032 // No further slashes. It's a child!
2033 rChildren.emplace_back(
2034 static_cast< Content * >( xChild.get() ) );
2041 uno::Reference< container::XHierarchicalNameAccess > Content::getPackage(
2042 const PackageUri& rURI )
2044 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2046 if ( rURI.getPackage() == m_aUri.getPackage() )
2048 if ( !m_xPackage.is() )
2049 m_xPackage = m_pProvider->createPackage( m_aUri );
2051 return m_xPackage;
2054 return m_pProvider->createPackage( rURI );
2058 uno::Reference< container::XHierarchicalNameAccess > Content::getPackage()
2060 return getPackage( m_aUri );
2064 // static
2065 bool Content::hasData(
2066 ContentProvider* pProvider,
2067 const PackageUri& rURI,
2068 uno::Reference< container::XHierarchicalNameAccess > & rxPackage )
2070 rxPackage = pProvider->createPackage( rURI );
2071 return rxPackage->hasByHierarchicalName( rURI.getPath() );
2075 bool Content::hasData( const PackageUri& rURI )
2077 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2079 uno::Reference< container::XHierarchicalNameAccess > xPackage;
2080 if ( rURI.getPackage() == m_aUri.getPackage() )
2082 xPackage = getPackage();
2083 return xPackage->hasByHierarchicalName( rURI.getPath() );
2086 return hasData( m_pProvider, rURI, xPackage );
2090 //static
2091 bool Content::loadData(
2092 ContentProvider* pProvider,
2093 const PackageUri& rURI,
2094 ContentProperties& rProps,
2095 uno::Reference< container::XHierarchicalNameAccess > & rxPackage )
2097 rxPackage = pProvider->createPackage( rURI );
2099 if ( rURI.isRootFolder() )
2101 // Properties available only from package
2102 uno::Reference< beans::XPropertySet > xPackagePropSet(
2103 rxPackage, uno::UNO_QUERY );
2105 OSL_ENSURE( xPackagePropSet.is(),
2106 "Content::loadData - "
2107 "Got no XPropertySet interface from package!" );
2109 if ( xPackagePropSet.is() )
2111 // HasEncryptedEntries (only available at root folder)
2114 uno::Any aHasEncryptedEntries
2115 = xPackagePropSet->getPropertyValue( "HasEncryptedEntries" );
2116 if ( !( aHasEncryptedEntries >>= rProps.bHasEncryptedEntries ) )
2118 OSL_FAIL( "Content::loadData - "
2119 "Got no HasEncryptedEntries value!" );
2120 return false;
2123 catch ( beans::UnknownPropertyException const & )
2125 OSL_FAIL( "Content::loadData - "
2126 "Got no HasEncryptedEntries value!" );
2127 return false;
2129 catch ( lang::WrappedTargetException const & )
2131 OSL_FAIL( "Content::loadData - "
2132 "Got no HasEncryptedEntries value!" );
2133 return false;
2138 if ( !rxPackage->hasByHierarchicalName( rURI.getPath() ) )
2139 return false;
2143 uno::Any aEntry = rxPackage->getByHierarchicalName( rURI.getPath() );
2144 if ( aEntry.hasValue() )
2146 uno::Reference< beans::XPropertySet > xPropSet;
2147 aEntry >>= xPropSet;
2149 if ( !xPropSet.is() )
2151 OSL_FAIL( "Content::loadData - Got no XPropertySet interface!" );
2152 return false;
2155 // Title
2156 rProps.aTitle = rURI.getName();
2158 // MediaType
2161 uno::Any aMediaType = xPropSet->getPropertyValue("MediaType");
2162 if ( !( aMediaType >>= rProps.aMediaType ) )
2164 OSL_FAIL( "Content::loadData - Got no MediaType value!" );
2165 return false;
2168 catch ( beans::UnknownPropertyException const & )
2170 OSL_FAIL( "Content::loadData - Got no MediaType value!" );
2171 return false;
2173 catch ( lang::WrappedTargetException const & )
2175 OSL_FAIL( "Content::loadData - Got no MediaType value!" );
2176 return false;
2179 uno::Reference< container::XEnumerationAccess > xEnumAccess;
2180 aEntry >>= xEnumAccess;
2182 // ContentType / IsFolder / IsDocument
2183 if ( xEnumAccess.is() )
2185 // folder
2186 rProps.aContentType = getContentType( rURI.getScheme(), true );
2187 rProps.bIsDocument = false;
2188 rProps.bIsFolder = true;
2190 else
2192 // stream
2193 rProps.aContentType = getContentType( rURI.getScheme(), false );
2194 rProps.bIsDocument = true;
2195 rProps.bIsFolder = false;
2198 if ( rProps.bIsDocument )
2200 // Size ( only available for streams )
2203 uno::Any aSize = xPropSet->getPropertyValue("Size");
2204 if ( !( aSize >>= rProps.nSize ) )
2206 OSL_FAIL( "Content::loadData - Got no Size value!" );
2207 return false;
2210 catch ( beans::UnknownPropertyException const & )
2212 OSL_FAIL( "Content::loadData - Got no Size value!" );
2213 return false;
2215 catch ( lang::WrappedTargetException const & )
2217 OSL_FAIL( "Content::loadData - Got no Size value!" );
2218 return false;
2221 // Compressed ( only available for streams )
2224 uno::Any aCompressed = xPropSet->getPropertyValue("Compressed");
2225 if ( !( aCompressed >>= rProps.bCompressed ) )
2227 OSL_FAIL( "Content::loadData - Got no Compressed value!" );
2228 return false;
2231 catch ( beans::UnknownPropertyException const & )
2233 OSL_FAIL( "Content::loadData - Got no Compressed value!" );
2234 return false;
2236 catch ( lang::WrappedTargetException const & )
2238 OSL_FAIL( "Content::loadData - Got no Compressed value!" );
2239 return false;
2242 // Encrypted ( only available for streams )
2245 uno::Any aEncrypted = xPropSet->getPropertyValue("Encrypted");
2246 if ( !( aEncrypted >>= rProps.bEncrypted ) )
2248 OSL_FAIL( "Content::loadData - Got no Encrypted value!" );
2249 return false;
2252 catch ( beans::UnknownPropertyException const & )
2254 OSL_FAIL( "Content::loadData - Got no Encrypted value!" );
2255 return false;
2257 catch ( lang::WrappedTargetException const & )
2259 OSL_FAIL( "Content::loadData - Got no Encrypted value!" );
2260 return false;
2263 return true;
2266 catch ( container::NoSuchElementException const & )
2268 // getByHierarchicalName
2271 return false;
2275 void Content::renameData(
2276 const uno::Reference< ucb::XContentIdentifier >& xOldId,
2277 const uno::Reference< ucb::XContentIdentifier >& xNewId )
2279 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2281 PackageUri aURI( xOldId->getContentIdentifier() );
2282 uno::Reference< container::XHierarchicalNameAccess > xNA = getPackage(
2283 aURI );
2285 if ( !xNA->hasByHierarchicalName( aURI.getPath() ) )
2286 return;
2290 uno::Any aEntry = xNA->getByHierarchicalName( aURI.getPath() );
2291 uno::Reference< container::XNamed > xNamed;
2292 aEntry >>= xNamed;
2294 if ( !xNamed.is() )
2296 OSL_FAIL( "Content::renameData - Got no XNamed interface!" );
2297 return;
2300 PackageUri aNewURI( xNewId->getContentIdentifier() );
2302 // No success indicator!? No return value / exceptions specified.
2303 xNamed->setName( aNewURI.getName() );
2305 catch ( container::NoSuchElementException const & )
2307 // getByHierarchicalName
2312 bool Content::storeData( const uno::Reference< io::XInputStream >& xStream )
2314 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2316 uno::Reference< container::XHierarchicalNameAccess > xNA = getPackage();
2318 uno::Reference< beans::XPropertySet > xPackagePropSet(
2319 xNA, uno::UNO_QUERY );
2320 OSL_ENSURE( xPackagePropSet.is(),
2321 "Content::storeData - "
2322 "Got no XPropertySet interface from package!" );
2324 if ( !xPackagePropSet.is() )
2325 return false;
2327 if ( m_nModifiedProps & ENCRYPTIONKEY_MODIFIED )
2329 if ( m_aUri.isRootFolder() )
2331 // Property available only from package and from streams (see below)
2334 xPackagePropSet->setPropertyValue(
2335 "EncryptionKey",
2336 uno::makeAny( m_aProps.aEncryptionKey ) );
2337 m_nModifiedProps &= ~ENCRYPTIONKEY_MODIFIED;
2339 catch ( beans::UnknownPropertyException const & )
2341 // setPropertyValue
2343 catch ( beans::PropertyVetoException const & )
2345 // setPropertyValue
2347 catch ( lang::IllegalArgumentException const & )
2349 // setPropertyValue
2351 catch ( lang::WrappedTargetException const & )
2353 // setPropertyValue
2358 if ( !xNA->hasByHierarchicalName( m_aUri.getPath() ) )
2360 // if ( !bCreate )
2361 // return sal_True;
2365 // Create new resource...
2366 uno::Reference< lang::XSingleServiceFactory > xFac(
2367 xNA, uno::UNO_QUERY );
2368 if ( !xFac.is() )
2370 OSL_FAIL( "Content::storeData - "
2371 "Got no XSingleServiceFactory interface!" );
2372 return false;
2375 uno::Sequence< uno::Any > aArgs( 1 );
2376 aArgs[ 0 ] <<= isFolder();
2378 uno::Reference< uno::XInterface > xNew
2379 = xFac->createInstanceWithArguments( aArgs );
2381 if ( !xNew.is() )
2383 OSL_FAIL( "Content::storeData - createInstance failed!" );
2384 return false;
2387 PackageUri aParentUri( getParentURL() );
2388 uno::Any aEntry
2389 = xNA->getByHierarchicalName( aParentUri.getPath() );
2390 uno::Reference< container::XNameContainer > xParentContainer;
2391 aEntry >>= xParentContainer;
2393 if ( !xParentContainer.is() )
2395 OSL_FAIL( "Content::storeData - "
2396 "Got no XNameContainer interface!" );
2397 return false;
2400 xParentContainer->insertByName( m_aProps.aTitle,
2401 uno::makeAny( xNew ) );
2403 catch ( lang::IllegalArgumentException const & )
2405 // insertByName
2406 OSL_FAIL( "Content::storeData - insertByName failed!" );
2407 return false;
2409 catch ( uno::RuntimeException const & )
2411 throw;
2413 catch ( container::ElementExistException const & )
2415 // insertByName
2416 OSL_FAIL( "Content::storeData - insertByName failed!" );
2417 return false;
2419 catch ( lang::WrappedTargetException const & )
2421 // insertByName
2422 OSL_FAIL( "Content::storeData - insertByName failed!" );
2423 return false;
2425 catch ( container::NoSuchElementException const & )
2427 // getByHierarchicalName
2428 OSL_FAIL( "Content::storeData - getByHierarchicalName failed!" );
2429 return false;
2431 catch ( uno::Exception const & )
2433 // createInstanceWithArguments
2434 OSL_FAIL( "Content::storeData - Error!" );
2435 return false;
2439 if ( !xNA->hasByHierarchicalName( m_aUri.getPath() ) )
2440 return false;
2444 uno::Reference< beans::XPropertySet > xPropSet;
2445 xNA->getByHierarchicalName( m_aUri.getPath() ) >>= xPropSet;
2447 if ( !xPropSet.is() )
2449 OSL_FAIL( "Content::storeData - Got no XPropertySet interface!" );
2450 return false;
2454 // Store property values...
2457 if ( m_nModifiedProps & MEDIATYPE_MODIFIED )
2459 xPropSet->setPropertyValue(
2460 "MediaType",
2461 uno::makeAny( m_aProps.aMediaType ) );
2462 m_nModifiedProps &= ~MEDIATYPE_MODIFIED;
2465 if ( m_nModifiedProps & COMPRESSED_MODIFIED )
2467 if ( !isFolder() )
2468 xPropSet->setPropertyValue(
2469 "Compressed",
2470 uno::makeAny( m_aProps.bCompressed ) );
2472 m_nModifiedProps &= ~COMPRESSED_MODIFIED;
2475 if ( m_nModifiedProps & ENCRYPTED_MODIFIED )
2477 if ( !isFolder() )
2478 xPropSet->setPropertyValue(
2479 "Encrypted",
2480 uno::makeAny( m_aProps.bEncrypted ) );
2482 m_nModifiedProps &= ~ENCRYPTED_MODIFIED;
2485 if ( m_nModifiedProps & ENCRYPTIONKEY_MODIFIED )
2487 if ( !isFolder() )
2488 xPropSet->setPropertyValue(
2489 "EncryptionKey",
2490 uno::makeAny( m_aProps.aEncryptionKey ) );
2492 m_nModifiedProps &= ~ENCRYPTIONKEY_MODIFIED;
2496 // Store data stream...
2499 if ( xStream.is() && !isFolder() )
2501 uno::Reference< io::XActiveDataSink > xSink(
2502 xPropSet, uno::UNO_QUERY );
2504 if ( !xSink.is() )
2506 OSL_FAIL( "Content::storeData - "
2507 "Got no XActiveDataSink interface!" );
2508 return false;
2511 xSink->setInputStream( xStream );
2514 return true;
2516 catch ( container::NoSuchElementException const & )
2518 // getByHierarchicalName
2520 catch ( beans::UnknownPropertyException const & )
2522 // setPropertyValue
2524 catch ( beans::PropertyVetoException const & )
2526 // setPropertyValue
2528 catch ( lang::IllegalArgumentException const & )
2530 // setPropertyValue
2532 catch ( lang::WrappedTargetException const & )
2534 // setPropertyValue
2537 OSL_FAIL( "Content::storeData - Error!" );
2538 return false;
2542 bool Content::removeData()
2544 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2546 uno::Reference< container::XHierarchicalNameAccess > xNA = getPackage();
2548 PackageUri aParentUri( getParentURL() );
2549 if ( !xNA->hasByHierarchicalName( aParentUri.getPath() ) )
2550 return false;
2554 uno::Any aEntry = xNA->getByHierarchicalName( aParentUri.getPath() );
2555 uno::Reference< container::XNameContainer > xContainer;
2556 aEntry >>= xContainer;
2558 if ( !xContainer.is() )
2560 OSL_FAIL( "Content::removeData - "
2561 "Got no XNameContainer interface!" );
2562 return false;
2565 xContainer->removeByName( m_aUri.getName() );
2566 return true;
2568 catch ( container::NoSuchElementException const & )
2570 // getByHierarchicalName, removeByName
2572 catch ( lang::WrappedTargetException const & )
2574 // removeByName
2577 OSL_FAIL( "Content::removeData - Error!" );
2578 return false;
2582 bool Content::flushData()
2584 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2586 // Note: XChangesBatch is only implemented by the package itself, not
2587 // by the single entries. Maybe this has to change...
2589 uno::Reference< container::XHierarchicalNameAccess > xNA = getPackage();
2591 uno::Reference< util::XChangesBatch > xBatch( xNA, uno::UNO_QUERY );
2592 if ( !xBatch.is() )
2594 OSL_FAIL( "Content::flushData - Got no XChangesBatch interface!" );
2595 return false;
2600 xBatch->commitChanges();
2601 return true;
2603 catch ( lang::WrappedTargetException const & )
2607 OSL_FAIL( "Content::flushData - Error!" );
2608 return false;
2612 uno::Reference< io::XInputStream > Content::getInputStream()
2614 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2616 uno::Reference< io::XInputStream > xStream;
2617 uno::Reference< container::XHierarchicalNameAccess > xNA = getPackage();
2619 if ( !xNA->hasByHierarchicalName( m_aUri.getPath() ) )
2620 return xStream;
2624 uno::Any aEntry = xNA->getByHierarchicalName( m_aUri.getPath() );
2625 uno::Reference< io::XActiveDataSink > xSink;
2626 aEntry >>= xSink;
2628 if ( !xSink.is() )
2630 OSL_FAIL( "Content::getInputStream - "
2631 "Got no XActiveDataSink interface!" );
2632 return xStream;
2635 xStream = xSink->getInputStream();
2637 OSL_ENSURE( xStream.is(),
2638 "Content::getInputStream - Got no stream!" );
2640 catch ( container::NoSuchElementException const & )
2642 // getByHierarchicalName
2645 return xStream;
2649 uno::Reference< container::XEnumeration > Content::getIterator()
2651 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2653 uno::Reference< container::XEnumeration > xIter;
2654 uno::Reference< container::XHierarchicalNameAccess > xNA = getPackage();
2656 if ( !xNA->hasByHierarchicalName( m_aUri.getPath() ) )
2657 return xIter;
2661 uno::Any aEntry = xNA->getByHierarchicalName( m_aUri.getPath() );
2662 uno::Reference< container::XEnumerationAccess > xIterFac;
2663 aEntry >>= xIterFac;
2665 if ( !xIterFac.is() )
2667 OSL_FAIL( "Content::getIterator - "
2668 "Got no XEnumerationAccess interface!" );
2669 return xIter;
2672 xIter = xIterFac->createEnumeration();
2674 OSL_ENSURE( xIter.is(),
2675 "Content::getIterator - Got no iterator!" );
2677 catch ( container::NoSuchElementException const & )
2679 // getByHierarchicalName
2682 return xIter;
2685 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */