LibreOffice Module ucb (master) 1
pkgcontent.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20
21/**************************************************************************
22 TODO
23 **************************************************************************
24 *************************************************************************/
25#include <sal/config.h>
26
27#include <string_view>
28
29#include <osl/diagnose.h>
30
31#include <rtl/ustring.hxx>
32#include <com/sun/star/beans/IllegalTypeException.hpp>
33#include <com/sun/star/beans/PropertyAttribute.hpp>
34#include <com/sun/star/beans/PropertyExistException.hpp>
35#include <com/sun/star/beans/PropertyState.hpp>
36#include <com/sun/star/container/XEnumerationAccess.hpp>
37#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
38#include <com/sun/star/container/XNameContainer.hpp>
39#include <com/sun/star/container/XNamed.hpp>
40#include <com/sun/star/io/BufferSizeExceededException.hpp>
41#include <com/sun/star/io/NotConnectedException.hpp>
42#include <com/sun/star/io/XActiveDataSink.hpp>
43#include <com/sun/star/io/XOutputStream.hpp>
44#include <com/sun/star/lang/IllegalAccessException.hpp>
45#include <com/sun/star/ucb/ContentInfoAttribute.hpp>
46#include <com/sun/star/ucb/IllegalIdentifierException.hpp>
47#include <com/sun/star/ucb/InsertCommandArgument.hpp>
48#include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp>
49#include <com/sun/star/ucb/MissingInputStreamException.hpp>
50#include <com/sun/star/ucb/NameClash.hpp>
51#include <com/sun/star/ucb/NameClashException.hpp>
52#include <com/sun/star/ucb/OpenCommandArgument2.hpp>
53#include <com/sun/star/ucb/OpenMode.hpp>
54#include <com/sun/star/ucb/TransferInfo.hpp>
55#include <com/sun/star/ucb/UnsupportedCommandException.hpp>
56#include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
57#include <com/sun/star/ucb/UnsupportedNameClashException.hpp>
58#include <com/sun/star/ucb/UnsupportedOpenModeException.hpp>
59#include <com/sun/star/ucb/XCommandInfo.hpp>
60#include <com/sun/star/ucb/XPersistentPropertySet.hpp>
61#include <com/sun/star/util/XChangesBatch.hpp>
62#include <com/sun/star/lang/XSingleServiceFactory.hpp>
63#include <com/sun/star/uno/Any.hxx>
64#include <com/sun/star/uno/Sequence.hxx>
70#include <ucbhelper/macros.hxx>
71#include <utility>
72#include "pkgcontent.hxx"
73#include "pkgprovider.hxx"
74#include "pkgresultset.hxx"
75
76#include "../inc/urihelper.hxx"
77
78using namespace com::sun::star;
79using namespace package_ucp;
80
81#define NONE_MODIFIED sal_uInt32( 0x00 )
82#define MEDIATYPE_MODIFIED sal_uInt32( 0x01 )
83#define COMPRESSED_MODIFIED sal_uInt32( 0x02 )
84#define ENCRYPTED_MODIFIED sal_uInt32( 0x04 )
85#define ENCRYPTIONKEY_MODIFIED sal_uInt32( 0x08 )
86
87
88// ContentProperties Implementation.
89
90
91ContentProperties::ContentProperties( const OUString& rContentType )
92: aContentType( rContentType ),
93 nSize( 0 ),
94 bCompressed( true ),
95 bEncrypted( false ),
96 bHasEncryptedEntries( false )
97{
100
101 OSL_ENSURE( bIsFolder || rContentType == PACKAGE_STREAM_CONTENT_TYPE || rContentType == PACKAGE_ZIP_STREAM_CONTENT_TYPE,
102 "ContentProperties::ContentProperties - Unknown type!" );
103}
104
105
106uno::Sequence< ucb::ContentInfo >
108{
109 if ( bIsFolder )
110 {
111 uno::Sequence< beans::Property > aProps( 1 );
112 aProps.getArray()[ 0 ] = beans::Property(
113 "Title",
114 -1,
116 beans::PropertyAttribute::BOUND );
117
118 uno::Sequence< ucb::ContentInfo > aSeq( 2 );
119
120 // Folder.
121 aSeq.getArray()[ 0 ].Type
122 = Content::getContentType( rUri.getScheme(), true );
123 aSeq.getArray()[ 0 ].Attributes
124 = ucb::ContentInfoAttribute::KIND_FOLDER;
125 aSeq.getArray()[ 0 ].Properties = aProps;
126
127 // Stream.
128 aSeq.getArray()[ 1 ].Type
129 = Content::getContentType( rUri.getScheme(), false );
130 aSeq.getArray()[ 1 ].Attributes
131 = ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM
132 | ucb::ContentInfoAttribute::KIND_DOCUMENT;
133 aSeq.getArray()[ 1 ].Properties = aProps;
134
135 return aSeq;
136 }
137 else
138 {
139 return uno::Sequence< ucb::ContentInfo >( 0 );
140 }
141}
142
143
144// Content Implementation.
145
146
147// static ( "virtual" ctor )
149 const uno::Reference< uno::XComponentContext >& rxContext,
150 ContentProvider* pProvider,
151 const uno::Reference< ucb::XContentIdentifier >& Identifier )
152{
153 OUString aURL = Identifier->getContentIdentifier();
154 PackageUri aURI( aURL );
155 ContentProperties aProps;
156 uno::Reference< container::XHierarchicalNameAccess > xPackage;
157
158 if ( loadData( pProvider, aURI, aProps, xPackage ) )
159 {
160 // resource exists
161
162 sal_Int32 nLastSlash = aURL.lastIndexOf( '/' );
163 if ( ( nLastSlash + 1 ) == aURL.getLength() )
164 {
165 // Client explicitly requested a folder!
166 if ( !aProps.bIsFolder )
167 return nullptr;
168 }
169
170 uno::Reference< ucb::XContentIdentifier > xId
171 = new ::ucbhelper::ContentIdentifier( aURI.getUri() );
172 return new Content( rxContext, pProvider, xId, xPackage, aURI, std::move(aProps) );
173 }
174 else
175 {
176 // resource doesn't exist
177
178 bool bFolder = false;
179
180 // Guess type according to URI.
181 sal_Int32 nLastSlash = aURL.lastIndexOf( '/' );
182 if ( ( nLastSlash + 1 ) == aURL.getLength() )
183 bFolder = true;
184
185 uno::Reference< ucb::XContentIdentifier > xId
186 = new ::ucbhelper::ContentIdentifier( aURI.getUri() );
187
188 ucb::ContentInfo aInfo;
189 if ( bFolder || aURI.isRootFolder() )
190 aInfo.Type = getContentType( aURI.getScheme(), true );
191 else
192 aInfo.Type = getContentType( aURI.getScheme(), false );
193
194 return new Content( rxContext, pProvider, xId, xPackage, aURI, aInfo );
195 }
196}
197
198
199// static ( "virtual" ctor )
201 const uno::Reference< uno::XComponentContext >& rxContext,
202 ContentProvider* pProvider,
203 const uno::Reference< ucb::XContentIdentifier >& Identifier,
204 const ucb::ContentInfo& Info )
205{
206 if ( Info.Type.isEmpty() )
207 return nullptr;
208
209 PackageUri aURI( Identifier->getContentIdentifier() );
210
211 if ( !Info.Type.equalsIgnoreAsciiCase(
212 getContentType( aURI.getScheme(), true ) ) &&
213 !Info.Type.equalsIgnoreAsciiCase(
214 getContentType( aURI.getScheme(), false ) ) )
215 return nullptr;
216
217 uno::Reference< container::XHierarchicalNameAccess > xPackage = pProvider->createPackage( aURI );
218
219 uno::Reference< ucb::XContentIdentifier > xId
220 = new ::ucbhelper::ContentIdentifier( aURI.getUri() );
221 return new Content( rxContext, pProvider, xId, xPackage, std::move(aURI), Info );
222}
223
224
225// static
227 std::u16string_view aScheme, bool bFolder )
228{
229 return ( OUString::Concat("application/")
230 + aScheme
231 + ( bFolder
232 ? std::u16string_view(u"-folder")
233 : std::u16string_view(u"-stream") ) );
234}
235
236
238 const uno::Reference< uno::XComponentContext >& rxContext,
239 ContentProvider* pProvider,
240 const uno::Reference< ucb::XContentIdentifier >& Identifier,
241 uno::Reference< container::XHierarchicalNameAccess > Package,
242 PackageUri aUri,
243 ContentProperties aProps )
244: ContentImplHelper( rxContext, pProvider, Identifier ),
245 m_aUri(std::move( aUri )),
246 m_aProps(std::move( aProps )),
247 m_eState( PERSISTENT ),
248 m_xPackage(std::move( Package )),
249 m_pProvider( pProvider ),
250 m_nModifiedProps( NONE_MODIFIED )
251{
252}
253
254
256 const uno::Reference< uno::XComponentContext >& rxContext,
257 ContentProvider* pProvider,
258 const uno::Reference< ucb::XContentIdentifier >& Identifier,
259 uno::Reference< container::XHierarchicalNameAccess > Package,
260 PackageUri aUri,
261 const ucb::ContentInfo& Info )
262 : ContentImplHelper( rxContext, pProvider, Identifier ),
263 m_aUri(std::move( aUri )),
264 m_aProps( Info.Type ),
265 m_eState( TRANSIENT ),
266 m_xPackage(std::move( Package )),
267 m_pProvider( pProvider ),
268 m_nModifiedProps( NONE_MODIFIED )
269{
270}
271
272
273// virtual
275{
276}
277
278
279// XInterface methods.
280
281
282// virtual
283void SAL_CALL Content::acquire()
284 noexcept
285{
286 ContentImplHelper::acquire();
287}
288
289
290// virtual
291void SAL_CALL Content::release()
292 noexcept
293{
294 ContentImplHelper::release();
295}
296
297
298// virtual
299uno::Any SAL_CALL Content::queryInterface( const uno::Type & rType )
300{
301 uno::Any aRet;
302
303 if ( isFolder() )
305 rType, static_cast< ucb::XContentCreator * >( this ) );
306
307 return aRet.hasValue() ? aRet : ContentImplHelper::queryInterface( rType );
308}
309
310
311// XTypeProvider methods.
312
313
315
316
317// virtual
318uno::Sequence< uno::Type > SAL_CALL Content::getTypes()
319{
320 if ( isFolder() )
321 {
322 static cppu::OTypeCollection s_aFolderTypes(
323 CPPU_TYPE_REF( lang::XTypeProvider ),
324 CPPU_TYPE_REF( lang::XServiceInfo ),
325 CPPU_TYPE_REF( lang::XComponent ),
326 CPPU_TYPE_REF( ucb::XContent ),
327 CPPU_TYPE_REF( ucb::XCommandProcessor ),
328 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
329 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
330 CPPU_TYPE_REF( beans::XPropertyContainer ),
331 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
332 CPPU_TYPE_REF( container::XChild ),
333 CPPU_TYPE_REF( ucb::XContentCreator ) );
334
335 return s_aFolderTypes.getTypes();
336
337 }
338 else
339 {
340 static cppu::OTypeCollection s_aDocumentTypes(
341 CPPU_TYPE_REF( lang::XTypeProvider ),
342 CPPU_TYPE_REF( lang::XServiceInfo ),
343 CPPU_TYPE_REF( lang::XComponent ),
344 CPPU_TYPE_REF( ucb::XContent ),
345 CPPU_TYPE_REF( ucb::XCommandProcessor ),
346 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
347 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
348 CPPU_TYPE_REF( beans::XPropertyContainer ),
349 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
350 CPPU_TYPE_REF( container::XChild ) );
351
352 return s_aDocumentTypes.getTypes();
353 }
354}
355
356
357// XServiceInfo methods.
358
359
360// virtual
362{
363 return "com.sun.star.comp.ucb.PackageContent";
364}
365
366
367// virtual
368uno::Sequence< OUString > SAL_CALL Content::getSupportedServiceNames()
369{
370 return { isFolder()? OUString("com.sun.star.ucb.PackageFolderContent"):OUString("com.sun.star.ucb.PackageStreamContent") } ;
371}
372
373
374// XContent methods.
375
376
377// virtual
378OUString SAL_CALL Content::getContentType()
379{
380 return m_aProps.aContentType;
381}
382
383
384// XCommandProcessor methods.
385
386
387// virtual
389 const ucb::Command& aCommand,
390 sal_Int32 /*CommandId*/,
391 const uno::Reference< ucb::XCommandEnvironment >& Environment )
392{
393 uno::Any aRet;
394
395 if ( aCommand.Name == "getPropertyValues" )
396 {
397
398 // getPropertyValues
399
400
401 uno::Sequence< beans::Property > Properties;
402 if ( !( aCommand.Argument >>= Properties ) )
403 {
405 uno::Any( lang::IllegalArgumentException(
406 "Wrong argument type!",
407 getXWeak(),
408 -1 ) ),
409 Environment );
410 // Unreachable
411 }
412
413 aRet <<= getPropertyValues( Properties );
414 }
415 else if ( aCommand.Name == "setPropertyValues" )
416 {
417
418 // setPropertyValues
419
420
421 uno::Sequence< beans::PropertyValue > aProperties;
422 if ( !( aCommand.Argument >>= aProperties ) )
423 {
425 uno::Any( lang::IllegalArgumentException(
426 "Wrong argument type!",
427 getXWeak(),
428 -1 ) ),
429 Environment );
430 // Unreachable
431 }
432
433 if ( !aProperties.hasElements() )
434 {
436 uno::Any( lang::IllegalArgumentException(
437 "No properties!",
438 getXWeak(),
439 -1 ) ),
440 Environment );
441 // Unreachable
442 }
443
444 aRet <<= setPropertyValues( aProperties, Environment );
445 }
446 else if ( aCommand.Name == "getPropertySetInfo" )
447 {
448
449 // getPropertySetInfo
450
451
452 // Note: Implemented by base class.
453 aRet <<= getPropertySetInfo( Environment );
454 }
455 else if ( aCommand.Name == "getCommandInfo" )
456 {
457
458 // getCommandInfo
459
460
461 // Note: Implemented by base class.
462 aRet <<= getCommandInfo( Environment );
463 }
464 else if ( aCommand.Name == "open" )
465 {
466
467 // open
468
469
470 ucb::OpenCommandArgument2 aOpenCommand;
471 if ( !( aCommand.Argument >>= aOpenCommand ) )
472 {
474 uno::Any( lang::IllegalArgumentException(
475 "Wrong argument type!",
476 getXWeak(),
477 -1 ) ),
478 Environment );
479 // Unreachable
480 }
481
482 aRet = open( aOpenCommand, Environment );
483 }
484 else if ( !m_aUri.isRootFolder() && aCommand.Name == "insert" )
485 {
486
487 // insert
488
489
490 ucb::InsertCommandArgument aArg;
491 if ( !( aCommand.Argument >>= aArg ) )
492 {
494 uno::Any( lang::IllegalArgumentException(
495 "Wrong argument type!",
496 getXWeak(),
497 -1 ) ),
498 Environment );
499 // Unreachable
500 }
501
502 sal_Int32 nNameClash = aArg.ReplaceExisting
503 ? ucb::NameClash::OVERWRITE
504 : ucb::NameClash::ERROR;
505 insert( aArg.Data, nNameClash, Environment );
506 }
507 else if ( !m_aUri.isRootFolder() && aCommand.Name == "delete" )
508 {
509
510 // delete
511
512
513 bool bDeletePhysical = false;
514 aCommand.Argument >>= bDeletePhysical;
515 destroy( bDeletePhysical, Environment );
516
517 // Remove own and all children's persistent data.
518 if ( !removeData() )
519 {
520 uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence(
521 {
522 {"Uri", uno::Any(m_xIdentifier->getContentIdentifier())}
523 }));
525 ucb::IOErrorCode_CANT_WRITE,
526 aArgs,
527 Environment,
528 "Cannot remove persistent data!",
529 this );
530 // Unreachable
531 }
532
533 // Remove own and all children's Additional Core Properties.
535 }
536 else if ( aCommand.Name == "transfer" )
537 {
538
539 // transfer
540 // ( Not available at stream objects )
541
542
543 ucb::TransferInfo aInfo;
544 if ( !( aCommand.Argument >>= aInfo ) )
545 {
547 uno::Any( lang::IllegalArgumentException(
548 "Wrong argument type!",
549 getXWeak(),
550 -1 ) ),
551 Environment );
552 // Unreachable
553 }
554
555 transfer( aInfo, Environment );
556 }
557 else if ( aCommand.Name == "createNewContent" && isFolder() )
558 {
559
560 // createNewContent
561 // ( Not available at stream objects )
562
563
564 ucb::ContentInfo aInfo;
565 if ( !( aCommand.Argument >>= aInfo ) )
566 {
567 OSL_FAIL( "Wrong argument type!" );
569 uno::Any( lang::IllegalArgumentException(
570 "Wrong argument type!",
571 getXWeak(),
572 -1 ) ),
573 Environment );
574 // Unreachable
575 }
576
577 aRet <<= createNewContent( aInfo );
578 }
579 else if ( aCommand.Name == "flush" )
580 {
581
582 // flush
583 // ( Not available at stream objects )
584
585
586 if( !flushData() )
587 {
588 uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence(
589 {
590 {"Uri", uno::Any(m_xIdentifier->getContentIdentifier())}
591 }));
593 ucb::IOErrorCode_CANT_WRITE,
594 aArgs,
595 Environment,
596 "Cannot write file to disk!",
597 this );
598 // Unreachable
599 }
600 }
601 else
602 {
603
604 // Unsupported command
605
606
608 uno::Any( ucb::UnsupportedCommandException(
609 OUString(),
610 getXWeak() ) ),
611 Environment );
612 // Unreachable
613 }
614
615 return aRet;
616}
617
618
619// virtual
620void SAL_CALL Content::abort( sal_Int32 /*CommandId*/ )
621{
622 // @@@ Implement logic to abort running commands, if this makes
623 // sense for your content.
624}
625
626
627// XContentCreator methods.
628
629
630// virtual
631uno::Sequence< ucb::ContentInfo > SAL_CALL
633{
635}
636
637
638// virtual
639uno::Reference< ucb::XContent > SAL_CALL
640Content::createNewContent( const ucb::ContentInfo& Info )
641{
642 if ( isFolder() )
643 {
644 osl::Guard< osl::Mutex > aGuard( m_aMutex );
645
646 if ( Info.Type.isEmpty() )
647 return uno::Reference< ucb::XContent >();
648
649 if ( !Info.Type.equalsIgnoreAsciiCase(
650 getContentType( m_aUri.getScheme(), true ) ) &&
651 !Info.Type.equalsIgnoreAsciiCase(
652 getContentType( m_aUri.getScheme(), false ) ) )
653 return uno::Reference< ucb::XContent >();
654
655 OUString aURL = m_aUri.getUri() + "/";
656
657 if ( Info.Type.equalsIgnoreAsciiCase(
658 getContentType( m_aUri.getScheme(), true ) ) )
659 aURL += "New_Folder";
660 else
661 aURL += "New_Stream";
662
663 uno::Reference< ucb::XContentIdentifier > xId(
664 new ::ucbhelper::ContentIdentifier( aURL ) );
665
666 return create( m_xContext, m_pProvider, xId, Info );
667 }
668 else
669 {
670 OSL_FAIL( "createNewContent called on non-folder object!" );
671 return uno::Reference< ucb::XContent >();
672 }
673}
674
675
676// Non-interface methods.
677
678
679// virtual
681{
682 return m_aUri.getParentUri();
683}
684
685
686// static
687uno::Reference< sdbc::XRow > Content::getPropertyValues(
688 const uno::Reference< uno::XComponentContext >& rxContext,
689 const uno::Sequence< beans::Property >& rProperties,
690 ContentProvider* pProvider,
691 const OUString& rContentId )
692{
694 uno::Reference< container::XHierarchicalNameAccess > xPackage;
695 if ( loadData( pProvider, PackageUri( rContentId ), aData, xPackage ) )
696 {
697 return getPropertyValues( rxContext,
698 rProperties,
699 aData,
702 pProvider ),
703 rContentId );
704 }
705 else
706 {
708 = new ::ucbhelper::PropertyValueSet( rxContext );
709
710 for ( const beans::Property& rProp : rProperties )
711 xRow->appendVoid( rProp );
712
713 return xRow;
714 }
715}
716
717
718// static
719uno::Reference< sdbc::XRow > Content::getPropertyValues(
720 const uno::Reference< uno::XComponentContext >& rxContext,
721 const uno::Sequence< beans::Property >& rProperties,
722 const ContentProperties& rData,
724 rProvider,
725 const OUString& rContentId )
726{
727 // Note: Empty sequence means "get values of all supported properties".
728
730 = new ::ucbhelper::PropertyValueSet( rxContext );
731
732 if ( rProperties.hasElements() )
733 {
734 uno::Reference< beans::XPropertySet > xAdditionalPropSet;
735 bool bTriedToGetAdditionalPropSet = false;
736
737 for ( const beans::Property& rProp : rProperties )
738 {
739 // Process Core properties.
740
741 if ( rProp.Name == "ContentType" )
742 {
743 xRow->appendString ( rProp, rData.aContentType );
744 }
745 else if ( rProp.Name == "Title" )
746 {
747 xRow->appendString ( rProp, rData.aTitle );
748 }
749 else if ( rProp.Name == "IsDocument" )
750 {
751 xRow->appendBoolean( rProp, rData.bIsDocument );
752 }
753 else if ( rProp.Name == "IsFolder" )
754 {
755 xRow->appendBoolean( rProp, rData.bIsFolder );
756 }
757 else if ( rProp.Name == "CreatableContentsInfo" )
758 {
759 xRow->appendObject(
760 rProp, uno::Any(
762 PackageUri( rContentId ) ) ) );
763 }
764 else if ( rProp.Name == "MediaType" )
765 {
766 xRow->appendString ( rProp, rData.aMediaType );
767 }
768 else if ( rProp.Name == "Size" )
769 {
770 // Property only available for streams.
771 if ( rData.bIsDocument )
772 xRow->appendLong( rProp, rData.nSize );
773 else
774 xRow->appendVoid( rProp );
775 }
776 else if ( rProp.Name == "Compressed" )
777 {
778 // Property only available for streams.
779 if ( rData.bIsDocument )
780 xRow->appendBoolean( rProp, rData.bCompressed );
781 else
782 xRow->appendVoid( rProp );
783 }
784 else if ( rProp.Name == "Encrypted" )
785 {
786 // Property only available for streams.
787 if ( rData.bIsDocument )
788 xRow->appendBoolean( rProp, rData.bEncrypted );
789 else
790 xRow->appendVoid( rProp );
791 }
792 else if ( rProp.Name == "HasEncryptedEntries" )
793 {
794 // Property only available for root folder.
795 PackageUri aURI( rContentId );
796 if ( aURI.isRootFolder() )
797 xRow->appendBoolean( rProp, rData.bHasEncryptedEntries );
798 else
799 xRow->appendVoid( rProp );
800 }
801 else
802 {
803 // Not a Core Property! Maybe it's an Additional Core Property?!
804
805 if ( !bTriedToGetAdditionalPropSet && !xAdditionalPropSet.is() )
806 {
807 xAdditionalPropSet =
808 rProvider->getAdditionalPropertySet( rContentId,
809 false );
810 bTriedToGetAdditionalPropSet = true;
811 }
812
813 if ( xAdditionalPropSet.is() )
814 {
815 if ( !xRow->appendPropertySetValue(
816 xAdditionalPropSet,
817 rProp ) )
818 {
819 // Append empty entry.
820 xRow->appendVoid( rProp );
821 }
822 }
823 else
824 {
825 // Append empty entry.
826 xRow->appendVoid( rProp );
827 }
828 }
829 }
830 }
831 else
832 {
833 // Append all Core Properties.
834 xRow->appendString (
835 beans::Property(
836 "ContentType",
837 -1,
839 beans::PropertyAttribute::BOUND
840 | beans::PropertyAttribute::READONLY ),
841 rData.aContentType );
842 xRow->appendString(
843 beans::Property(
844 "Title",
845 -1,
847 beans::PropertyAttribute::BOUND ),
848 rData.aTitle );
849 xRow->appendBoolean(
850 beans::Property(
851 "IsDocument",
852 -1,
854 beans::PropertyAttribute::BOUND
855 | beans::PropertyAttribute::READONLY ),
856 rData.bIsDocument );
857 xRow->appendBoolean(
858 beans::Property(
859 "IsFolder",
860 -1,
862 beans::PropertyAttribute::BOUND
863 | beans::PropertyAttribute::READONLY ),
864 rData.bIsFolder );
865 xRow->appendObject(
866 beans::Property(
867 "CreatableContentsInfo",
868 -1,
869 cppu::UnoType<uno::Sequence< ucb::ContentInfo >>::get(),
870 beans::PropertyAttribute::BOUND
871 | beans::PropertyAttribute::READONLY ),
872 uno::Any(
873 rData.getCreatableContentsInfo( PackageUri( rContentId ) ) ) );
874 xRow->appendString(
875 beans::Property(
876 "MediaType",
877 -1,
879 beans::PropertyAttribute::BOUND ),
880 rData.aMediaType );
881
882 // Properties only available for streams.
883 if ( rData.bIsDocument )
884 {
885 xRow->appendLong(
886 beans::Property(
887 "Size",
888 -1,
890 beans::PropertyAttribute::BOUND
891 | beans::PropertyAttribute::READONLY ),
892 rData.nSize );
893
894 xRow->appendBoolean(
895 beans::Property(
896 "Compressed",
897 -1,
899 beans::PropertyAttribute::BOUND ),
900 rData.bCompressed );
901
902 xRow->appendBoolean(
903 beans::Property(
904 "Encrypted",
905 -1,
907 beans::PropertyAttribute::BOUND ),
908 rData.bEncrypted );
909 }
910
911 // Properties only available for root folder.
912 PackageUri aURI( rContentId );
913 if ( aURI.isRootFolder() )
914 {
915 xRow->appendBoolean(
916 beans::Property(
917 "HasEncryptedEntries",
918 -1,
920 beans::PropertyAttribute::BOUND
921 | beans::PropertyAttribute::READONLY ),
922 rData.bHasEncryptedEntries );
923 }
924
925 // Append all Additional Core Properties.
926
927 uno::Reference< beans::XPropertySet > xSet =
928 rProvider->getAdditionalPropertySet( rContentId, false );
929 xRow->appendPropertySet( xSet );
930 }
931
932 return xRow;
933}
934
935
936uno::Reference< sdbc::XRow > Content::getPropertyValues(
937 const uno::Sequence< beans::Property >& rProperties )
938{
939 osl::Guard< osl::Mutex > aGuard( m_aMutex );
941 rProperties,
942 m_aProps,
944 m_xIdentifier->getContentIdentifier() );
945}
946
947
948uno::Sequence< uno::Any > Content::setPropertyValues(
949 const uno::Sequence< beans::PropertyValue >& rValues,
950 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
951{
952 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
953
954 uno::Sequence< uno::Any > aRet( rValues.getLength() );
955 auto aRetRange = asNonConstRange(aRet);
956 uno::Sequence< beans::PropertyChangeEvent > aChanges( rValues.getLength() );
957 sal_Int32 nChanged = 0;
958
959 beans::PropertyChangeEvent aEvent;
960 aEvent.Source = getXWeak();
961 aEvent.Further = false;
962// aEvent.PropertyName =
963 aEvent.PropertyHandle = -1;
964// aEvent.OldValue =
965// aEvent.NewValue =
966
967 const beans::PropertyValue* pValues = rValues.getConstArray();
968 sal_Int32 nCount = rValues.getLength();
969
970 uno::Reference< ucb::XPersistentPropertySet > xAdditionalPropSet;
971 bool bTriedToGetAdditionalPropSet = false;
972 bool bExchange = false;
973 bool bStore = false;
974 OUString aNewTitle;
975 sal_Int32 nTitlePos = -1;
976
977 for ( sal_Int32 n = 0; n < nCount; ++n )
978 {
979 const beans::PropertyValue& rValue = pValues[ n ];
980
981 if ( rValue.Name == "ContentType" )
982 {
983 // Read-only property!
984 aRetRange[ n ] <<= lang::IllegalAccessException(
985 "Property is read-only!",
986 getXWeak() );
987 }
988 else if ( rValue.Name == "IsDocument" )
989 {
990 // Read-only property!
991 aRetRange[ n ] <<= lang::IllegalAccessException(
992 "Property is read-only!",
993 getXWeak() );
994 }
995 else if ( rValue.Name == "IsFolder" )
996 {
997 // Read-only property!
998 aRetRange[ n ] <<= lang::IllegalAccessException(
999 "Property is read-only!",
1000 getXWeak() );
1001 }
1002 else if ( rValue.Name == "CreatableContentsInfo" )
1003 {
1004 // Read-only property!
1005 aRetRange[ n ] <<= lang::IllegalAccessException(
1006 "Property is read-only!",
1007 getXWeak() );
1008 }
1009 else if ( rValue.Name == "Title" )
1010 {
1011 if ( m_aUri.isRootFolder() )
1012 {
1013 // Read-only property!
1014 aRetRange[ n ] <<= lang::IllegalAccessException(
1015 "Property is read-only!",
1016 getXWeak() );
1017 }
1018 else
1019 {
1020 OUString aNewValue;
1021 if ( rValue.Value >>= aNewValue )
1022 {
1023 // No empty titles!
1024 if ( !aNewValue.isEmpty() )
1025 {
1026 if ( aNewValue != m_aProps.aTitle )
1027 {
1028 // modified title -> modified URL -> exchange !
1029 if ( m_eState == PERSISTENT )
1030 bExchange = true;
1031
1032 // new value will be set later...
1033 aNewTitle = aNewValue;
1034
1035 // remember position within sequence of values
1036 // (for error handling).
1037 nTitlePos = n;
1038 }
1039 }
1040 else
1041 {
1042 aRetRange[ n ] <<=
1043 lang::IllegalArgumentException(
1044 "Empty title not allowed!",
1045 getXWeak(),
1046 -1 );
1047 }
1048 }
1049 else
1050 {
1051 aRetRange[ n ] <<=
1052 beans::IllegalTypeException(
1053 "Property value has wrong type!",
1054 getXWeak() );
1055 }
1056 }
1057 }
1058 else if ( rValue.Name == "MediaType" )
1059 {
1060 OUString aNewValue;
1061 if ( rValue.Value >>= aNewValue )
1062 {
1063 if ( aNewValue != m_aProps.aMediaType )
1064 {
1065 aEvent.PropertyName = rValue.Name;
1066 aEvent.OldValue <<= m_aProps.aMediaType;
1067 aEvent.NewValue <<= aNewValue;
1068
1069 m_aProps.aMediaType = aNewValue;
1070 nChanged++;
1071 bStore = true;
1073 }
1074 }
1075 else
1076 {
1077 aRetRange[ n ] <<= beans::IllegalTypeException(
1078 "Property value has wrong type!",
1079 getXWeak() );
1080 }
1081 }
1082 else if ( rValue.Name == "Size" )
1083 {
1084 // Read-only property!
1085 aRetRange[ n ] <<= lang::IllegalAccessException(
1086 "Property is read-only!",
1087 getXWeak() );
1088 }
1089 else if ( rValue.Name == "Compressed" )
1090 {
1091 // Property only available for streams.
1092 if ( m_aProps.bIsDocument )
1093 {
1094 bool bNewValue;
1095 if ( rValue.Value >>= bNewValue )
1096 {
1097 if ( bNewValue != m_aProps.bCompressed )
1098 {
1099 aEvent.PropertyName = rValue.Name;
1100 aEvent.OldValue <<= m_aProps.bCompressed;
1101 aEvent.NewValue <<= bNewValue;
1102
1103 m_aProps.bCompressed = bNewValue;
1104 nChanged++;
1105 bStore = true;
1107 }
1108 }
1109 else
1110 {
1111 aRetRange[ n ] <<= beans::IllegalTypeException(
1112 "Property value has wrong type!",
1113 getXWeak() );
1114 }
1115 }
1116 else
1117 {
1118 aRetRange[ n ] <<= beans::UnknownPropertyException(
1119 "Compressed only supported by streams!",
1120 getXWeak() );
1121 }
1122 }
1123 else if ( rValue.Name == "Encrypted" )
1124 {
1125 // Property only available for streams.
1126 if ( m_aProps.bIsDocument )
1127 {
1128 bool bNewValue;
1129 if ( rValue.Value >>= bNewValue )
1130 {
1131 if ( bNewValue != m_aProps.bEncrypted )
1132 {
1133 aEvent.PropertyName = rValue.Name;
1134 aEvent.OldValue <<= m_aProps.bEncrypted;
1135 aEvent.NewValue <<= bNewValue;
1136
1137 m_aProps.bEncrypted = bNewValue;
1138 nChanged++;
1139 bStore = true;
1141 }
1142 }
1143 else
1144 {
1145 aRetRange[ n ] <<= beans::IllegalTypeException(
1146 "Property value has wrong type!",
1147 getXWeak() );
1148 }
1149 }
1150 else
1151 {
1152 aRetRange[ n ] <<= beans::UnknownPropertyException(
1153 "Encrypted only supported by streams!",
1154 getXWeak() );
1155 }
1156 }
1157 else if ( rValue.Name == "HasEncryptedEntries" )
1158 {
1159 // Read-only property!
1160 aRetRange[ n ] <<= lang::IllegalAccessException(
1161 "Property is read-only!",
1162 getXWeak() );
1163 }
1164 else if ( rValue.Name == "EncryptionKey" )
1165 {
1166 // @@@ This is a temporary solution. In the future submitting
1167 // the key should be done using an interaction handler!
1168
1169 // Write-Only property. Only supported by root folder and streams
1170 // (all non-root folders of a package have the same encryption key).
1172 {
1173 uno::Sequence < sal_Int8 > aNewValue;
1174 if ( rValue.Value >>= aNewValue )
1175 {
1176 if ( aNewValue != m_aProps.aEncryptionKey )
1177 {
1178 aEvent.PropertyName = rValue.Name;
1179 aEvent.OldValue <<= m_aProps.aEncryptionKey;
1180 aEvent.NewValue <<= aNewValue;
1181
1182 m_aProps.aEncryptionKey = aNewValue;
1183 nChanged++;
1184 bStore = true;
1186 }
1187 }
1188 else
1189 {
1190 aRetRange[ n ] <<= beans::IllegalTypeException(
1191 "Property value has wrong type!",
1192 getXWeak() );
1193 }
1194 }
1195 else
1196 {
1197 aRetRange[ n ] <<= beans::UnknownPropertyException(
1198 "EncryptionKey not supported by non-root folder!",
1199 getXWeak() );
1200 }
1201 }
1202 else
1203 {
1204 // Not a Core Property! Maybe it's an Additional Core Property?!
1205
1206 if ( !bTriedToGetAdditionalPropSet && !xAdditionalPropSet.is() )
1207 {
1208 xAdditionalPropSet = getAdditionalPropertySet( false );
1209 bTriedToGetAdditionalPropSet = true;
1210 }
1211
1212 if ( xAdditionalPropSet.is() )
1213 {
1214 try
1215 {
1216 uno::Any aOldValue
1217 = xAdditionalPropSet->getPropertyValue( rValue.Name );
1218 if ( aOldValue != rValue.Value )
1219 {
1220 xAdditionalPropSet->setPropertyValue(
1221 rValue.Name, rValue.Value );
1222
1223 aEvent.PropertyName = rValue.Name;
1224 aEvent.OldValue = aOldValue;
1225 aEvent.NewValue = rValue.Value;
1226
1227 aChanges.getArray()[ nChanged ] = aEvent;
1228 nChanged++;
1229 }
1230 }
1231 catch ( beans::UnknownPropertyException const & e )
1232 {
1233 aRetRange[ n ] <<= e;
1234 }
1235 catch ( lang::WrappedTargetException const & e )
1236 {
1237 aRetRange[ n ] <<= e;
1238 }
1239 catch ( beans::PropertyVetoException const & e )
1240 {
1241 aRetRange[ n ] <<= e;
1242 }
1243 catch ( lang::IllegalArgumentException const & e )
1244 {
1245 aRetRange[ n ] <<= e;
1246 }
1247 }
1248 else
1249 {
1250 aRetRange[ n ] <<= uno::Exception(
1251 "No property set for storing the value!",
1252 getXWeak() );
1253 }
1254 }
1255 }
1256
1257 if ( bExchange )
1258 {
1259 uno::Reference< ucb::XContentIdentifier > xOldId = m_xIdentifier;
1260
1261 // Assemble new content identifier...
1262 OUString aNewURL = m_aUri.getParentUri() + "/" +
1264 uno::Reference< ucb::XContentIdentifier > xNewId
1265 = new ::ucbhelper::ContentIdentifier( aNewURL );
1266
1267 aGuard.clear();
1268 if ( exchangeIdentity( xNewId ) )
1269 {
1270 // Adapt persistent data.
1271 renameData( xOldId, xNewId );
1272
1273 // Adapt Additional Core Properties.
1274 renameAdditionalPropertySet( xOldId->getContentIdentifier(),
1275 xNewId->getContentIdentifier() );
1276 }
1277 else
1278 {
1279 // Do not set new title!
1280 aNewTitle.clear();
1281
1282 // Set error .
1283 aRetRange[ nTitlePos ] <<= uno::Exception(
1284 "Exchange failed!",
1285 getXWeak() );
1286 }
1287 }
1288
1289 if ( !aNewTitle.isEmpty() )
1290 {
1291 aEvent.PropertyName = "Title";
1292 aEvent.OldValue <<= m_aProps.aTitle;
1293 aEvent.NewValue <<= aNewTitle;
1294
1295 m_aProps.aTitle = aNewTitle;
1296
1297 aChanges.getArray()[ nChanged ] = aEvent;
1298 nChanged++;
1299 }
1300
1301 if ( nChanged > 0 )
1302 {
1303 // Save changes, if content was already made persistent.
1305 ( bStore && ( m_eState == PERSISTENT ) ) )
1306 {
1307 if ( !storeData( uno::Reference< io::XInputStream >() ) )
1308 {
1309 uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence(
1310 {
1311 {"Uri", uno::Any(m_xIdentifier->getContentIdentifier())}
1312 }));
1314 ucb::IOErrorCode_CANT_WRITE,
1315 aArgs,
1316 xEnv,
1317 "Cannot store persistent data!",
1318 this );
1319 // Unreachable
1320 }
1321 }
1322
1323 aGuard.clear();
1324 aChanges.realloc( nChanged );
1325 notifyPropertiesChange( aChanges );
1326 }
1327
1328 return aRet;
1329}
1330
1331
1333 const ucb::OpenCommandArgument2& rArg,
1334 const uno::Reference< ucb::XCommandEnvironment >& xEnv )
1335{
1336 if ( rArg.Mode == ucb::OpenMode::ALL ||
1337 rArg.Mode == ucb::OpenMode::FOLDERS ||
1338 rArg.Mode == ucb::OpenMode::DOCUMENTS )
1339 {
1340
1341 // open command for a folder content
1342
1343
1344 uno::Reference< ucb::XDynamicResultSet > xSet
1345 = new DynamicResultSet( m_xContext, this, rArg, xEnv );
1346 return uno::Any( xSet );
1347 }
1348 else
1349 {
1350
1351 // open command for a document content
1352
1353
1354 if ( ( rArg.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE ) ||
1355 ( rArg.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE ) )
1356 {
1357 // Currently(?) unsupported.
1359 uno::Any( ucb::UnsupportedOpenModeException(
1360 OUString(),
1361 getXWeak(),
1362 sal_Int16( rArg.Mode ) ) ),
1363 xEnv );
1364 // Unreachable
1365 }
1366
1367 uno::Reference< io::XOutputStream > xOut( rArg.Sink, uno::UNO_QUERY );
1368 if ( xOut.is() )
1369 {
1370 // PUSH: write data into xOut
1371
1372 uno::Reference< io::XInputStream > xIn = getInputStream();
1373 if ( !xIn.is() )
1374 {
1375 // No interaction if we are not persistent!
1376 uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence(
1377 {
1378 {"Uri", uno::Any(m_xIdentifier->getContentIdentifier())}
1379 }));
1381 ucb::IOErrorCode_CANT_READ,
1382 aArgs,
1384 ? xEnv
1385 : uno::Reference< ucb::XCommandEnvironment >(),
1386 "Got no data stream!",
1387 this );
1388 // Unreachable
1389 }
1390
1391 try
1392 {
1393 uno::Sequence< sal_Int8 > aBuffer;
1394 while (true)
1395 {
1396 sal_Int32 nRead = xIn->readSomeBytes( aBuffer, 65536 );
1397 if (!nRead)
1398 break;
1399 aBuffer.realloc( nRead );
1400 xOut->writeBytes( aBuffer );
1401 }
1402
1403 xOut->closeOutput();
1404 }
1405 catch ( io::NotConnectedException const & )
1406 {
1407 // closeOutput, readSomeBytes, writeBytes
1408 }
1409 catch ( io::BufferSizeExceededException const & )
1410 {
1411 // closeOutput, readSomeBytes, writeBytes
1412 }
1413 catch ( io::IOException const & )
1414 {
1415 // closeOutput, readSomeBytes, writeBytes
1416 }
1417 }
1418 else
1419 {
1420 uno::Reference< io::XActiveDataSink > xDataSink(
1421 rArg.Sink, uno::UNO_QUERY );
1422 if ( xDataSink.is() )
1423 {
1424 // PULL: wait for client read
1425
1426 uno::Reference< io::XInputStream > xIn = getInputStream();
1427 if ( !xIn.is() )
1428 {
1429 // No interaction if we are not persistent!
1430 uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence(
1431 {
1432 {"Uri", uno::Any(m_xIdentifier->getContentIdentifier())}
1433 }));
1435 ucb::IOErrorCode_CANT_READ,
1436 aArgs,
1438 ? xEnv
1439 : uno::Reference<
1440 ucb::XCommandEnvironment >(),
1441 "Got no data stream!",
1442 this );
1443 // Unreachable
1444 }
1445
1446 // Done.
1447 xDataSink->setInputStream( xIn );
1448 }
1449 else
1450 {
1451 // Note: aOpenCommand.Sink may contain an XStream
1452 // implementation. Support for this type of
1453 // sink is optional...
1455 uno::Any(
1456 ucb::UnsupportedDataSinkException(
1457 OUString(),
1458 getXWeak(),
1459 rArg.Sink ) ),
1460 xEnv );
1461 // Unreachable
1462 }
1463 }
1464 }
1465
1466 return uno::Any();
1467}
1468
1469
1470void Content::insert(
1471 const uno::Reference< io::XInputStream >& xStream,
1472 sal_Int32 nNameClashResolve,
1473 const uno::Reference< ucb::XCommandEnvironment >& xEnv )
1474{
1475 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1476
1477 // Check, if all required properties were set.
1478 if ( isFolder() )
1479 {
1480 // Required: Title
1481
1482 if ( m_aProps.aTitle.isEmpty() )
1484 }
1485 else
1486 {
1487 // Required: rArg.Data
1488
1489 if ( !xStream.is() )
1490 {
1492 uno::Any( ucb::MissingInputStreamException(
1493 OUString(),
1494 getXWeak() ) ),
1495 xEnv );
1496 // Unreachable
1497 }
1498
1499 // Required: Title
1500
1501 if ( m_aProps.aTitle.isEmpty() )
1503 }
1504
1505 OUString aNewURL = m_aUri.getParentUri();
1506 if (1 + aNewURL.lastIndexOf('/') != aNewURL.getLength())
1507 aNewURL += "/";
1509 PackageUri aNewUri( aNewURL );
1510
1511 // Handle possible name clash...
1512 switch ( nNameClashResolve )
1513 {
1514 // fail.
1515 case ucb::NameClash::ERROR:
1516 if ( hasData( aNewUri ) )
1517 {
1519 uno::Any( ucb::NameClashException(
1520 OUString(),
1521 getXWeak(),
1522 task::InteractionClassification_ERROR,
1523 m_aProps.aTitle ) ),
1524 xEnv );
1525 // Unreachable
1526 }
1527 break;
1528
1529 // replace (possibly) existing object.
1530 case ucb::NameClash::OVERWRITE:
1531 break;
1532
1533 // "invent" a new valid title.
1534 case ucb::NameClash::RENAME:
1535 if ( hasData( aNewUri ) )
1536 {
1537 sal_Int32 nTry = 0;
1538
1539 do
1540 {
1541 OUString aNew = aNewUri.getUri() + "_" + OUString::number( ++nTry );
1542 aNewUri.setUri( aNew );
1543 }
1544 while ( hasData( aNewUri ) && ( nTry < 1000 ) );
1545
1546 if ( nTry == 1000 )
1547 {
1549 uno::Any(
1550 ucb::UnsupportedNameClashException(
1551 "Unable to resolve name clash!",
1552 getXWeak(),
1553 nNameClashResolve ) ),
1554 xEnv );
1555 // Unreachable
1556 }
1557 else
1558 {
1559 m_aProps.aTitle += "_";
1560 m_aProps.aTitle += OUString::number( nTry );
1561 }
1562 }
1563 break;
1564
1565 case ucb::NameClash::KEEP: // deprecated
1566 case ucb::NameClash::ASK:
1567 default:
1568 if ( hasData( aNewUri ) )
1569 {
1571 uno::Any(
1572 ucb::UnsupportedNameClashException(
1573 OUString(),
1574 getXWeak(),
1575 nNameClashResolve ) ),
1576 xEnv );
1577 // Unreachable
1578 }
1579 break;
1580 }
1581
1582 // Identifier changed?
1583 bool bNewId = ( m_aUri.getUri() != aNewUri.getUri() );
1584
1585 if ( bNewId )
1586 {
1587 m_xIdentifier = new ::ucbhelper::ContentIdentifier( aNewURL );
1588 m_aUri = aNewUri;
1589 }
1590
1591 if ( !storeData( xStream ) )
1592 {
1593 uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence(
1594 {
1595 {"Uri", uno::Any(m_xIdentifier->getContentIdentifier())}
1596 }));
1598 ucb::IOErrorCode_CANT_WRITE,
1599 aArgs,
1600 xEnv,
1601 "Cannot store persistent data!",
1602 this );
1603 // Unreachable
1604 }
1605
1607
1608 if ( bNewId )
1609 {
1610 // Take over correct default values from underlying packager...
1611 uno::Reference< container::XHierarchicalNameAccess > xXHierarchicalNameAccess;
1613 m_aUri,
1614 m_aProps,
1615 xXHierarchicalNameAccess );
1616
1617 aGuard.clear();
1618 inserted();
1619 }
1620}
1621
1622
1623void Content::destroy(
1624 bool bDeletePhysical,
1625 const uno::Reference< ucb::XCommandEnvironment >& xEnv )
1626{
1627 // @@@ take care about bDeletePhysical -> trashcan support
1628
1629 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1630
1631 uno::Reference< ucb::XContent > xThis = this;
1632
1633 // Persistent?
1634 if ( m_eState != PERSISTENT )
1635 {
1637 uno::Any( ucb::UnsupportedCommandException(
1638 "Not persistent!",
1639 getXWeak() ) ),
1640 xEnv );
1641 // Unreachable
1642 }
1643
1644 m_eState = DEAD;
1645
1646 aGuard.clear();
1647 deleted();
1648
1649 if ( isFolder() )
1650 {
1651 // Process instantiated children...
1652
1653 ContentRefList aChildren;
1654 queryChildren( aChildren );
1655
1656 for ( auto& rChild : aChildren )
1657 {
1658 rChild->destroy( bDeletePhysical, xEnv );
1659 }
1660 }
1661}
1662
1663
1665 const ucb::TransferInfo& rInfo,
1666 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
1667{
1668 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1669
1670 // Persistent?
1671 if ( m_eState != PERSISTENT )
1672 {
1674 uno::Any( ucb::UnsupportedCommandException(
1675 "Not persistent!",
1676 getXWeak() ) ),
1677 xEnv );
1678 // Unreachable
1679 }
1680
1681 // Is source a package content?
1682 if ( ( rInfo.SourceURL.isEmpty() ) ||
1683 ( rInfo.SourceURL.compareTo(
1684 m_aUri.getUri(), PACKAGE_URL_SCHEME_LENGTH + 3 ) != 0 ) )
1685 {
1687 uno::Any( ucb::InteractiveBadTransferURLException(
1688 OUString(),
1689 getXWeak() ) ),
1690 xEnv );
1691 // Unreachable
1692 }
1693
1694 // Is source not a parent of me / not me?
1695 OUString aId = m_aUri.getParentUri() + "/";
1696
1697 if ( rInfo.SourceURL.getLength() <= aId.getLength() )
1698 {
1699 if ( aId.startsWith( rInfo.SourceURL ) )
1700 {
1701 uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence(
1702 {
1703 {"Uri", uno::Any(rInfo.SourceURL)}
1704 }));
1706 ucb::IOErrorCode_RECURSIVE,
1707 aArgs,
1708 xEnv,
1709 "Target is equal to or is a child of source!",
1710 this );
1711 // Unreachable
1712 }
1713 }
1714
1715
1716 // 0) Obtain content object for source.
1717
1718
1719 uno::Reference< ucb::XContentIdentifier > xId
1720 = new ::ucbhelper::ContentIdentifier( rInfo.SourceURL );
1721
1722 // Note: The static cast is okay here, because its sure that
1723 // m_xProvider is always the PackageContentProvider.
1725
1726 try
1727 {
1728 xSource = static_cast< Content * >(
1729 m_xProvider->queryContent( xId ).get() );
1730 }
1731 catch ( ucb::IllegalIdentifierException const & )
1732 {
1733 // queryContent
1734 }
1735
1736 if ( !xSource.is() )
1737 {
1738 uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence(
1739 {
1740 {"Uri", uno::Any(xId->getContentIdentifier())}
1741 }));
1743 ucb::IOErrorCode_CANT_READ,
1744 aArgs,
1745 xEnv,
1746 "Cannot instantiate source object!",
1747 this );
1748 // Unreachable
1749 }
1750
1751
1752 // 1) Create new child content.
1753
1754
1755 OUString aType = xSource->isFolder()
1756 ? getContentType( m_aUri.getScheme(), true )
1757 : getContentType( m_aUri.getScheme(), false );
1758 ucb::ContentInfo aContentInfo;
1759 aContentInfo.Type = aType;
1760 aContentInfo.Attributes = 0;
1761
1762 // Note: The static cast is okay here, because its sure that
1763 // createNewContent always creates a Content.
1765 = static_cast< Content * >( createNewContent( aContentInfo ).get() );
1766 if ( !xTarget.is() )
1767 {
1768 uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence(
1769 {
1770 {"Folder", uno::Any(aId)}
1771 }));
1773 ucb::IOErrorCode_CANT_CREATE,
1774 aArgs,
1775 xEnv,
1776 "XContentCreator::createNewContent failed!",
1777 this );
1778 // Unreachable
1779 }
1780
1781
1782 // 2) Copy data from source content to child content.
1783
1784
1785 uno::Sequence< beans::Property > aSourceProps
1786 = xSource->getPropertySetInfo( xEnv )->getProperties();
1787 sal_Int32 nCount = aSourceProps.getLength();
1788
1789 if ( nCount )
1790 {
1791 bool bHadTitle = rInfo.NewTitle.isEmpty();
1792
1793 // Get all source values.
1794 uno::Reference< sdbc::XRow > xRow
1795 = xSource->getPropertyValues( aSourceProps );
1796
1797 uno::Sequence< beans::PropertyValue > aValues( nCount );
1798 beans::PropertyValue* pValues = aValues.getArray();
1799
1800 const beans::Property* pProps = aSourceProps.getConstArray();
1801 for ( sal_Int32 n = 0; n < nCount; ++n )
1802 {
1803 const beans::Property& rProp = pProps[ n ];
1804 beans::PropertyValue& rValue = pValues[ n ];
1805
1806 rValue.Name = rProp.Name;
1807 rValue.Handle = rProp.Handle;
1808
1809 if ( !bHadTitle && rProp.Name == "Title" )
1810 {
1811 // Set new title instead of original.
1812 bHadTitle = true;
1813 rValue.Value <<= rInfo.NewTitle;
1814 }
1815 else
1816 rValue.Value
1817 = xRow->getObject( n + 1,
1818 uno::Reference<
1819 container::XNameAccess >() );
1820
1821 rValue.State = beans::PropertyState_DIRECT_VALUE;
1822
1823 if ( rProp.Attributes & beans::PropertyAttribute::REMOVABLE )
1824 {
1825 // Add Additional Core Property.
1826 try
1827 {
1828 xTarget->addProperty( rProp.Name,
1829 rProp.Attributes,
1830 rValue.Value );
1831 }
1832 catch ( beans::PropertyExistException const & )
1833 {
1834 }
1835 catch ( beans::IllegalTypeException const & )
1836 {
1837 }
1838 catch ( lang::IllegalArgumentException const & )
1839 {
1840 }
1841 }
1842 }
1843
1844 // Set target values.
1845 xTarget->setPropertyValues( aValues, xEnv );
1846 }
1847
1848
1849 // 3) Commit (insert) child.
1850
1851
1852 xTarget->insert( xSource->getInputStream(), rInfo.NameClash, xEnv );
1853
1854
1855 // 4) Transfer (copy) children of source.
1856
1857
1858 if ( xSource->isFolder() )
1859 {
1860 uno::Reference< container::XEnumeration > xIter
1861 = xSource->getIterator();
1862 if ( xIter.is() )
1863 {
1864 while ( xIter->hasMoreElements() )
1865 {
1866 try
1867 {
1868 uno::Reference< container::XNamed > xNamed;
1869 xIter->nextElement() >>= xNamed;
1870
1871 if ( !xNamed.is() )
1872 {
1873 OSL_FAIL( "Content::transfer - Got no XNamed!" );
1874 break;
1875 }
1876
1877 OUString aName = xNamed->getName();
1878
1879 if ( aName.isEmpty() )
1880 {
1881 OSL_FAIL( "Content::transfer - Empty name!" );
1882 break;
1883 }
1884
1885 OUString aChildId = xId->getContentIdentifier();
1886 if ( ( aChildId.lastIndexOf( '/' ) + 1 )
1887 != aChildId.getLength() )
1888 aChildId += "/";
1889
1890 aChildId += ::ucb_impl::urihelper::encodeSegment( aName );
1891
1892 ucb::TransferInfo aInfo;
1893 aInfo.MoveData = false;
1894 aInfo.NewTitle.clear();
1895 aInfo.SourceURL = aChildId;
1896 aInfo.NameClash = rInfo.NameClash;
1897
1898 // Transfer child to target.
1899 xTarget->transfer( aInfo, xEnv );
1900 }
1901 catch ( container::NoSuchElementException const & )
1902 {
1903 }
1904 catch ( lang::WrappedTargetException const & )
1905 {
1906 }
1907 }
1908 }
1909 }
1910
1911
1912 // 5) Destroy source ( when moving only ) .
1913
1914
1915 if ( !rInfo.MoveData )
1916 return;
1917
1918 xSource->destroy( true, xEnv );
1919
1920 // Remove all persistent data of source and its children.
1921 if ( !xSource->removeData() )
1922 {
1923 uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence(
1924 {
1925 {"Uri", uno::Any(xSource->m_xIdentifier->getContentIdentifier())}
1926 }));
1928 ucb::IOErrorCode_CANT_WRITE,
1929 aArgs,
1930 xEnv,
1931 "Cannot remove persistent data of source object!",
1932 this );
1933 // Unreachable
1934 }
1935
1936 // Remove own and all children's Additional Core Properties.
1937 xSource->removeAdditionalPropertySet();
1938}
1939
1940
1942 const uno::Reference< ucb::XContentIdentifier >& xNewId )
1943{
1944 if ( !xNewId.is() )
1945 return false;
1946
1947 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1948
1949 uno::Reference< ucb::XContent > xThis = this;
1950
1951 // Already persistent?
1952 if ( m_eState != PERSISTENT )
1953 {
1954 OSL_FAIL( "Content::exchangeIdentity - Not persistent!" );
1955 return false;
1956 }
1957
1958 // Exchange own identity.
1959
1960 // Fail, if a content with given id already exists.
1961 PackageUri aNewUri( xNewId->getContentIdentifier() );
1962 if ( !hasData( aNewUri ) )
1963 {
1964 OUString aOldURL = m_xIdentifier->getContentIdentifier();
1965
1966 aGuard.clear();
1967 if ( exchange( xNewId ) )
1968 {
1969 m_aUri = aNewUri;
1970 if ( isFolder() )
1971 {
1972 // Process instantiated children...
1973
1974 ContentRefList aChildren;
1975 queryChildren( aChildren );
1976
1977 for ( const auto& rChild : aChildren )
1978 {
1979 ContentRef xChild = rChild;
1980
1981 // Create new content identifier for the child...
1982 uno::Reference< ucb::XContentIdentifier > xOldChildId
1983 = xChild->getIdentifier();
1984 OUString aOldChildURL
1985 = xOldChildId->getContentIdentifier();
1986 OUString aNewChildURL
1987 = aOldChildURL.replaceAt(
1988 0,
1989 aOldURL.getLength(),
1990 xNewId->getContentIdentifier() );
1991 uno::Reference< ucb::XContentIdentifier > xNewChildId
1992 = new ::ucbhelper::ContentIdentifier( aNewChildURL );
1993
1994 if ( !xChild->exchangeIdentity( xNewChildId ) )
1995 return false;
1996 }
1997 }
1998 return true;
1999 }
2000 }
2001
2002 OSL_FAIL( "Content::exchangeIdentity - Panic! Cannot exchange identity!" );
2003 return false;
2004}
2005
2006
2008{
2009 // Obtain a list with a snapshot of all currently instantiated contents
2010 // from provider and extract the contents which are direct children
2011 // of this content.
2012
2013 ::ucbhelper::ContentRefList aAllContents;
2014 m_xProvider->queryExistingContents( aAllContents );
2015
2016 OUString aURL = m_xIdentifier->getContentIdentifier();
2017
2018 OSL_ENSURE( aURL.lastIndexOf( '/' ) != ( aURL.getLength() - 1 ),
2019 "Content::queryChildren - Invalid URL!" );
2020
2021 aURL += "/";
2022
2023 sal_Int32 nLen = aURL.getLength();
2024
2025 for ( const auto& rContent : aAllContents )
2026 {
2027 ::ucbhelper::ContentImplHelperRef xChild = rContent;
2028 OUString aChildURL
2029 = xChild->getIdentifier()->getContentIdentifier();
2030
2031 // Is aURL a prefix of aChildURL?
2032 if ( ( aChildURL.getLength() > nLen ) &&
2033 ( aChildURL.startsWith( aURL ) ) )
2034 {
2035 if ( aChildURL.indexOf( '/', nLen ) == -1 )
2036 {
2037 // No further slashes. It's a child!
2038 rChildren.emplace_back(
2039 static_cast< Content * >( xChild.get() ) );
2040 }
2041 }
2042 }
2043}
2044
2045
2046uno::Reference< container::XHierarchicalNameAccess > Content::getPackage(
2047 const PackageUri& rURI )
2048{
2049 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2050
2051 if ( rURI.getPackage() == m_aUri.getPackage() )
2052 {
2053 if ( !m_xPackage.is() )
2055
2056 return m_xPackage;
2057 }
2058
2059 return m_pProvider->createPackage( rURI );
2060}
2061
2062
2063uno::Reference< container::XHierarchicalNameAccess > Content::getPackage()
2064{
2065 return getPackage( m_aUri );
2066}
2067
2068
2069// static
2070bool Content::hasData(
2071 ContentProvider* pProvider,
2072 const PackageUri& rURI,
2073 uno::Reference< container::XHierarchicalNameAccess > & rxPackage )
2074{
2075 rxPackage = pProvider->createPackage( rURI );
2076 return rxPackage->hasByHierarchicalName( rURI.getPath() );
2077}
2078
2079
2080bool Content::hasData( const PackageUri& rURI )
2081{
2082 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2083
2084 uno::Reference< container::XHierarchicalNameAccess > xPackage;
2085 if ( rURI.getPackage() == m_aUri.getPackage() )
2086 {
2087 xPackage = getPackage();
2088 return xPackage->hasByHierarchicalName( rURI.getPath() );
2089 }
2090
2091 return hasData( m_pProvider, rURI, xPackage );
2092}
2093
2094
2095//static
2097 ContentProvider* pProvider,
2098 const PackageUri& rURI,
2099 ContentProperties& rProps,
2100 uno::Reference< container::XHierarchicalNameAccess > & rxPackage )
2101{
2102 rxPackage = pProvider->createPackage( rURI );
2103
2104 if ( rURI.isRootFolder() )
2105 {
2106 // Properties available only from package
2107 uno::Reference< beans::XPropertySet > xPackagePropSet(
2108 rxPackage, uno::UNO_QUERY );
2109
2110 OSL_ENSURE( xPackagePropSet.is(),
2111 "Content::loadData - "
2112 "Got no XPropertySet interface from package!" );
2113
2114 if ( xPackagePropSet.is() )
2115 {
2116 // HasEncryptedEntries (only available at root folder)
2117 try
2118 {
2119 uno::Any aHasEncryptedEntries
2120 = xPackagePropSet->getPropertyValue( "HasEncryptedEntries" );
2121 if ( !( aHasEncryptedEntries >>= rProps.bHasEncryptedEntries ) )
2122 {
2123 OSL_FAIL( "Content::loadData - "
2124 "Got no HasEncryptedEntries value!" );
2125 return false;
2126 }
2127 }
2128 catch ( beans::UnknownPropertyException const & )
2129 {
2130 OSL_FAIL( "Content::loadData - "
2131 "Got no HasEncryptedEntries value!" );
2132 return false;
2133 }
2134 catch ( lang::WrappedTargetException const & )
2135 {
2136 OSL_FAIL( "Content::loadData - "
2137 "Got no HasEncryptedEntries value!" );
2138 return false;
2139 }
2140 }
2141 }
2142
2143 if ( !rxPackage->hasByHierarchicalName( rURI.getPath() ) )
2144 return false;
2145
2146 try
2147 {
2148 uno::Any aEntry = rxPackage->getByHierarchicalName( rURI.getPath() );
2149 if ( aEntry.hasValue() )
2150 {
2151 uno::Reference< beans::XPropertySet > xPropSet;
2152 aEntry >>= xPropSet;
2153
2154 if ( !xPropSet.is() )
2155 {
2156 OSL_FAIL( "Content::loadData - Got no XPropertySet interface!" );
2157 return false;
2158 }
2159
2160 // Title
2161 rProps.aTitle = rURI.getName();
2162
2163 // MediaType
2164 try
2165 {
2166 uno::Any aMediaType = xPropSet->getPropertyValue("MediaType");
2167 if ( !( aMediaType >>= rProps.aMediaType ) )
2168 {
2169 OSL_FAIL( "Content::loadData - Got no MediaType value!" );
2170 return false;
2171 }
2172 }
2173 catch ( beans::UnknownPropertyException const & )
2174 {
2175 OSL_FAIL( "Content::loadData - Got no MediaType value!" );
2176 return false;
2177 }
2178 catch ( lang::WrappedTargetException const & )
2179 {
2180 OSL_FAIL( "Content::loadData - Got no MediaType value!" );
2181 return false;
2182 }
2183
2184 uno::Reference< container::XEnumerationAccess > xEnumAccess;
2185 aEntry >>= xEnumAccess;
2186
2187 // ContentType / IsFolder / IsDocument
2188 if ( xEnumAccess.is() )
2189 {
2190 // folder
2191 rProps.aContentType = getContentType( rURI.getScheme(), true );
2192 rProps.bIsDocument = false;
2193 rProps.bIsFolder = true;
2194 }
2195 else
2196 {
2197 // stream
2198 rProps.aContentType = getContentType( rURI.getScheme(), false );
2199 rProps.bIsDocument = true;
2200 rProps.bIsFolder = false;
2201 }
2202
2203 if ( rProps.bIsDocument )
2204 {
2205 // Size ( only available for streams )
2206 try
2207 {
2208 uno::Any aSize = xPropSet->getPropertyValue("Size");
2209 if ( !( aSize >>= rProps.nSize ) )
2210 {
2211 OSL_FAIL( "Content::loadData - Got no Size value!" );
2212 return false;
2213 }
2214 }
2215 catch ( beans::UnknownPropertyException const & )
2216 {
2217 OSL_FAIL( "Content::loadData - Got no Size value!" );
2218 return false;
2219 }
2220 catch ( lang::WrappedTargetException const & )
2221 {
2222 OSL_FAIL( "Content::loadData - Got no Size value!" );
2223 return false;
2224 }
2225
2226 // Compressed ( only available for streams )
2227 try
2228 {
2229 uno::Any aCompressed = xPropSet->getPropertyValue("Compressed");
2230 if ( !( aCompressed >>= rProps.bCompressed ) )
2231 {
2232 OSL_FAIL( "Content::loadData - Got no Compressed value!" );
2233 return false;
2234 }
2235 }
2236 catch ( beans::UnknownPropertyException const & )
2237 {
2238 OSL_FAIL( "Content::loadData - Got no Compressed value!" );
2239 return false;
2240 }
2241 catch ( lang::WrappedTargetException const & )
2242 {
2243 OSL_FAIL( "Content::loadData - Got no Compressed value!" );
2244 return false;
2245 }
2246
2247 // Encrypted ( only available for streams )
2248 try
2249 {
2250 uno::Any aEncrypted = xPropSet->getPropertyValue("Encrypted");
2251 if ( !( aEncrypted >>= rProps.bEncrypted ) )
2252 {
2253 OSL_FAIL( "Content::loadData - Got no Encrypted value!" );
2254 return false;
2255 }
2256 }
2257 catch ( beans::UnknownPropertyException const & )
2258 {
2259 OSL_FAIL( "Content::loadData - Got no Encrypted value!" );
2260 return false;
2261 }
2262 catch ( lang::WrappedTargetException const & )
2263 {
2264 OSL_FAIL( "Content::loadData - Got no Encrypted value!" );
2265 return false;
2266 }
2267 }
2268 return true;
2269 }
2270 }
2271 catch ( container::NoSuchElementException const & )
2272 {
2273 // getByHierarchicalName
2274 }
2275
2276 return false;
2277}
2278
2279
2281 const uno::Reference< ucb::XContentIdentifier >& xOldId,
2282 const uno::Reference< ucb::XContentIdentifier >& xNewId )
2283{
2284 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2285
2286 PackageUri aURI( xOldId->getContentIdentifier() );
2287 uno::Reference< container::XHierarchicalNameAccess > xNA = getPackage(
2288 aURI );
2289
2290 if ( !xNA->hasByHierarchicalName( aURI.getPath() ) )
2291 return;
2292
2293 try
2294 {
2295 uno::Any aEntry = xNA->getByHierarchicalName( aURI.getPath() );
2296 uno::Reference< container::XNamed > xNamed;
2297 aEntry >>= xNamed;
2298
2299 if ( !xNamed.is() )
2300 {
2301 OSL_FAIL( "Content::renameData - Got no XNamed interface!" );
2302 return;
2303 }
2304
2305 PackageUri aNewURI( xNewId->getContentIdentifier() );
2306
2307 // No success indicator!? No return value / exceptions specified.
2308 xNamed->setName( aNewURI.getName() );
2309 }
2310 catch ( container::NoSuchElementException const & )
2311 {
2312 // getByHierarchicalName
2313 }
2314}
2315
2316
2317bool Content::storeData( const uno::Reference< io::XInputStream >& xStream )
2318{
2319 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2320
2321 uno::Reference< container::XHierarchicalNameAccess > xNA = getPackage();
2322
2323 uno::Reference< beans::XPropertySet > xPackagePropSet(
2324 xNA, uno::UNO_QUERY );
2325 OSL_ENSURE( xPackagePropSet.is(),
2326 "Content::storeData - "
2327 "Got no XPropertySet interface from package!" );
2328
2329 if ( !xPackagePropSet.is() )
2330 return false;
2331
2333 {
2334 if ( m_aUri.isRootFolder() )
2335 {
2336 // Property available only from package and from streams (see below)
2337 try
2338 {
2339 xPackagePropSet->setPropertyValue(
2340 "EncryptionKey",
2342 m_nModifiedProps &= ~ENCRYPTIONKEY_MODIFIED;
2343 }
2344 catch ( beans::UnknownPropertyException const & )
2345 {
2346 // setPropertyValue
2347 }
2348 catch ( beans::PropertyVetoException const & )
2349 {
2350 // setPropertyValue
2351 }
2352 catch ( lang::IllegalArgumentException const & )
2353 {
2354 // setPropertyValue
2355 }
2356 catch ( lang::WrappedTargetException const & )
2357 {
2358 // setPropertyValue
2359 }
2360 }
2361 }
2362
2363 if ( !xNA->hasByHierarchicalName( m_aUri.getPath() ) )
2364 {
2365// if ( !bCreate )
2366// return sal_True;
2367
2368 try
2369 {
2370 // Create new resource...
2371 uno::Reference< lang::XSingleServiceFactory > xFac(
2372 xNA, uno::UNO_QUERY );
2373 if ( !xFac.is() )
2374 {
2375 OSL_FAIL( "Content::storeData - "
2376 "Got no XSingleServiceFactory interface!" );
2377 return false;
2378 }
2379
2380 uno::Sequence< uno::Any > aArgs{ uno::Any(isFolder()) };
2381
2382 uno::Reference< uno::XInterface > xNew
2383 = xFac->createInstanceWithArguments( aArgs );
2384
2385 if ( !xNew.is() )
2386 {
2387 OSL_FAIL( "Content::storeData - createInstance failed!" );
2388 return false;
2389 }
2390
2391 PackageUri aParentUri( getParentURL() );
2392 uno::Any aEntry
2393 = xNA->getByHierarchicalName( aParentUri.getPath() );
2394 uno::Reference< container::XNameContainer > xParentContainer;
2395 aEntry >>= xParentContainer;
2396
2397 if ( !xParentContainer.is() )
2398 {
2399 OSL_FAIL( "Content::storeData - "
2400 "Got no XNameContainer interface!" );
2401 return false;
2402 }
2403
2404 xParentContainer->insertByName( m_aProps.aTitle,
2405 uno::Any( xNew ) );
2406 }
2407 catch ( lang::IllegalArgumentException const & )
2408 {
2409 // insertByName
2410 OSL_FAIL( "Content::storeData - insertByName failed!" );
2411 return false;
2412 }
2413 catch ( uno::RuntimeException const & )
2414 {
2415 throw;
2416 }
2417 catch ( container::ElementExistException const & )
2418 {
2419 // insertByName
2420 OSL_FAIL( "Content::storeData - insertByName failed!" );
2421 return false;
2422 }
2423 catch ( lang::WrappedTargetException const & )
2424 {
2425 // insertByName
2426 OSL_FAIL( "Content::storeData - insertByName failed!" );
2427 return false;
2428 }
2429 catch ( container::NoSuchElementException const & )
2430 {
2431 // getByHierarchicalName
2432 OSL_FAIL( "Content::storeData - getByHierarchicalName failed!" );
2433 return false;
2434 }
2435 catch ( uno::Exception const & )
2436 {
2437 // createInstanceWithArguments
2438 OSL_FAIL( "Content::storeData - Error!" );
2439 return false;
2440 }
2441 }
2442
2443 if ( !xNA->hasByHierarchicalName( m_aUri.getPath() ) )
2444 return false;
2445
2446 try
2447 {
2448 uno::Reference< beans::XPropertySet > xPropSet;
2449 xNA->getByHierarchicalName( m_aUri.getPath() ) >>= xPropSet;
2450
2451 if ( !xPropSet.is() )
2452 {
2453 OSL_FAIL( "Content::storeData - Got no XPropertySet interface!" );
2454 return false;
2455 }
2456
2457
2458 // Store property values...
2459
2460
2462 {
2463 xPropSet->setPropertyValue(
2464 "MediaType",
2466 m_nModifiedProps &= ~MEDIATYPE_MODIFIED;
2467 }
2468
2470 {
2471 if ( !isFolder() )
2472 xPropSet->setPropertyValue(
2473 "Compressed",
2475
2476 m_nModifiedProps &= ~COMPRESSED_MODIFIED;
2477 }
2478
2480 {
2481 if ( !isFolder() )
2482 xPropSet->setPropertyValue(
2483 "Encrypted",
2485
2486 m_nModifiedProps &= ~ENCRYPTED_MODIFIED;
2487 }
2488
2490 {
2491 if ( !isFolder() )
2492 xPropSet->setPropertyValue(
2493 "EncryptionKey",
2495
2496 m_nModifiedProps &= ~ENCRYPTIONKEY_MODIFIED;
2497 }
2498
2499
2500 // Store data stream...
2501
2502
2503 if ( xStream.is() && !isFolder() )
2504 {
2505 uno::Reference< io::XActiveDataSink > xSink(
2506 xPropSet, uno::UNO_QUERY );
2507
2508 if ( !xSink.is() )
2509 {
2510 OSL_FAIL( "Content::storeData - "
2511 "Got no XActiveDataSink interface!" );
2512 return false;
2513 }
2514
2515 xSink->setInputStream( xStream );
2516 }
2517
2518 return true;
2519 }
2520 catch ( container::NoSuchElementException const & )
2521 {
2522 // getByHierarchicalName
2523 }
2524 catch ( beans::UnknownPropertyException const & )
2525 {
2526 // setPropertyValue
2527 }
2528 catch ( beans::PropertyVetoException const & )
2529 {
2530 // setPropertyValue
2531 }
2532 catch ( lang::IllegalArgumentException const & )
2533 {
2534 // setPropertyValue
2535 }
2536 catch ( lang::WrappedTargetException const & )
2537 {
2538 // setPropertyValue
2539 }
2540
2541 OSL_FAIL( "Content::storeData - Error!" );
2542 return false;
2543}
2544
2545
2547{
2548 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2549
2550 uno::Reference< container::XHierarchicalNameAccess > xNA = getPackage();
2551
2552 PackageUri aParentUri( getParentURL() );
2553 if ( !xNA->hasByHierarchicalName( aParentUri.getPath() ) )
2554 return false;
2555
2556 try
2557 {
2558 uno::Any aEntry = xNA->getByHierarchicalName( aParentUri.getPath() );
2559 uno::Reference< container::XNameContainer > xContainer;
2560 aEntry >>= xContainer;
2561
2562 if ( !xContainer.is() )
2563 {
2564 OSL_FAIL( "Content::removeData - "
2565 "Got no XNameContainer interface!" );
2566 return false;
2567 }
2568
2569 xContainer->removeByName( m_aUri.getName() );
2570 return true;
2571 }
2572 catch ( container::NoSuchElementException const & )
2573 {
2574 // getByHierarchicalName, removeByName
2575 }
2576 catch ( lang::WrappedTargetException const & )
2577 {
2578 // removeByName
2579 }
2580
2581 OSL_FAIL( "Content::removeData - Error!" );
2582 return false;
2583}
2584
2585
2587{
2588 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2589
2590 // Note: XChangesBatch is only implemented by the package itself, not
2591 // by the single entries. Maybe this has to change...
2592
2593 uno::Reference< container::XHierarchicalNameAccess > xNA = getPackage();
2594
2595 uno::Reference< util::XChangesBatch > xBatch( xNA, uno::UNO_QUERY );
2596 if ( !xBatch.is() )
2597 {
2598 OSL_FAIL( "Content::flushData - Got no XChangesBatch interface!" );
2599 return false;
2600 }
2601
2602 try
2603 {
2604 xBatch->commitChanges();
2605 return true;
2606 }
2607 catch ( lang::WrappedTargetException const & )
2608 {
2609 }
2610
2611 OSL_FAIL( "Content::flushData - Error!" );
2612 return false;
2613}
2614
2615
2616uno::Reference< io::XInputStream > Content::getInputStream()
2617{
2618 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2619
2620 uno::Reference< io::XInputStream > xStream;
2621 uno::Reference< container::XHierarchicalNameAccess > xNA = getPackage();
2622
2623 if ( !xNA->hasByHierarchicalName( m_aUri.getPath() ) )
2624 return xStream;
2625
2626 try
2627 {
2628 uno::Any aEntry = xNA->getByHierarchicalName( m_aUri.getPath() );
2629 uno::Reference< io::XActiveDataSink > xSink;
2630 aEntry >>= xSink;
2631
2632 if ( !xSink.is() )
2633 {
2634 OSL_FAIL( "Content::getInputStream - "
2635 "Got no XActiveDataSink interface!" );
2636 return xStream;
2637 }
2638
2639 xStream = xSink->getInputStream();
2640
2641 OSL_ENSURE( xStream.is(),
2642 "Content::getInputStream - Got no stream!" );
2643 }
2644 catch ( container::NoSuchElementException const & )
2645 {
2646 // getByHierarchicalName
2647 }
2648
2649 return xStream;
2650}
2651
2652
2653uno::Reference< container::XEnumeration > Content::getIterator()
2654{
2655 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2656
2657 uno::Reference< container::XEnumeration > xIter;
2658 uno::Reference< container::XHierarchicalNameAccess > xNA = getPackage();
2659
2660 if ( !xNA->hasByHierarchicalName( m_aUri.getPath() ) )
2661 return xIter;
2662
2663 try
2664 {
2665 uno::Any aEntry = xNA->getByHierarchicalName( m_aUri.getPath() );
2666 uno::Reference< container::XEnumerationAccess > xIterFac;
2667 aEntry >>= xIterFac;
2668
2669 if ( !xIterFac.is() )
2670 {
2671 OSL_FAIL( "Content::getIterator - "
2672 "Got no XEnumerationAccess interface!" );
2673 return xIter;
2674 }
2675
2676 xIter = xIterFac->createEnumeration();
2677
2678 OSL_ENSURE( xIter.is(),
2679 "Content::getIterator - Got no iterator!" );
2680 }
2681 catch ( container::NoSuchElementException const & )
2682 {
2683 // getByHierarchicalName
2684 }
2685
2686 return xIter;
2687}
2688
2689/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const PropertyValue * pValues
PropertiesInfo aProperties
Reference< XInputStream > xStream
AnyEventRef aEvent
css::uno::Sequence< css::uno::Type > SAL_CALL getTypes()
css::uno::Reference< css::container::XHierarchicalNameAccess > createPackage(const PackageUri &rParam)
bool storeData(const css::uno::Reference< css::io::XInputStream > &xStream)
rtl::Reference< Content > ContentRef
Definition: pkgcontent.hxx:168
bool exchangeIdentity(const css::uno::Reference< css::ucb::XContentIdentifier > &xNewId)
css::uno::Reference< css::container::XHierarchicalNameAccess > getPackage()
static css::uno::Reference< css::sdbc::XRow > getPropertyValues(const css::uno::Reference< css::uno::XComponentContext > &rxContext, const css::uno::Sequence< css::beans::Property > &rProperties, const ContentProperties &rData, const rtl::Reference< ::ucbhelper::ContentProviderImplHelper > &rProvider, const OUString &rContentId)
virtual css::uno::Sequence< css::ucb::ContentInfo > SAL_CALL queryCreatableContentsInfo() override
Definition: pkgcontent.cxx:632
css::uno::Any open(const css::ucb::OpenCommandArgument2 &rArg, const css::uno::Reference< css::ucb::XCommandEnvironment > &xEnv)
bool isFolder() const
Definition: pkgcontent.hxx:198
static bool loadData(ContentProvider *pProvider, const PackageUri &rURI, ContentProperties &rProps, css::uno::Reference< css::container::XHierarchicalNameAccess > &rxPackage)
ContentProperties m_aProps
Definition: pkgcontent.hxx:99
void destroy(bool bDeletePhysical, const css::uno::Reference< css::ucb::XCommandEnvironment > &xEnv)
Content(const css::uno::Reference< css::uno::XComponentContext > &rxContext, ContentProvider *pProvider, const css::uno::Reference< css::ucb::XContentIdentifier > &Identifier, css::uno::Reference< css::container::XHierarchicalNameAccess > Package, PackageUri aUri, ContentProperties aProps)
css::uno::Reference< css::io::XInputStream > getInputStream()
static rtl::Reference< Content > create(const css::uno::Reference< css::uno::XComponentContext > &rxContext, ContentProvider *pProvider, const css::uno::Reference< css::ucb::XContentIdentifier > &Identifier)
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType) override
css::uno::Reference< css::container::XHierarchicalNameAccess > m_xPackage
Definition: pkgcontent.hxx:102
virtual css::uno::Reference< css::ucb::XContent > SAL_CALL createNewContent(const css::ucb::ContentInfo &Info) override
virtual css::uno::Any SAL_CALL execute(const css::ucb::Command &aCommand, sal_Int32 CommandId, const css::uno::Reference< css::ucb::XCommandEnvironment > &Environment) override
virtual OUString SAL_CALL getImplementationName() override
Definition: pkgcontent.cxx:361
std::vector< ContentRef > ContentRefList
Definition: pkgcontent.hxx:169
virtual void SAL_CALL acquire() noexcept override
Definition: pkgcontent.cxx:283
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
Definition: pkgcontent.cxx:368
ContentProvider * m_pProvider
Definition: pkgcontent.hxx:103
virtual void SAL_CALL release() noexcept override
Definition: pkgcontent.cxx:291
virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override
Definition: pkgcontent.cxx:318
void renameData(const css::uno::Reference< css::ucb::XContentIdentifier > &xOldId, const css::uno::Reference< css::ucb::XContentIdentifier > &xNewId)
void transfer(const css::ucb::TransferInfo &rInfo, const css::uno::Reference< css::ucb::XCommandEnvironment > &xEnv)
sal_uInt32 m_nModifiedProps
Definition: pkgcontent.hxx:104
void queryChildren(ContentRefList &rChildren)
virtual OUString SAL_CALL getContentType() override
Definition: pkgcontent.cxx:378
virtual void SAL_CALL abort(sal_Int32 CommandId) override
Definition: pkgcontent.cxx:620
virtual OUString getParentURL() override
Definition: pkgcontent.cxx:680
ContentState m_eState
Definition: pkgcontent.hxx:100
static bool hasData(ContentProvider *pProvider, const PackageUri &rURI, css::uno::Reference< css::container::XHierarchicalNameAccess > &rxPackage)
void insert(const css::uno::Reference< css::io::XInputStream > &xStream, sal_Int32 nNameClashResolve, const css::uno::Reference< css::ucb::XCommandEnvironment > &xEnv)
css::uno::Reference< css::container::XEnumeration > getIterator()
css::uno::Sequence< css::uno::Any > setPropertyValues(const css::uno::Sequence< css::beans::PropertyValue > &rValues, const css::uno::Reference< css::ucb::XCommandEnvironment > &xEnv)
virtual ~Content() override
Definition: pkgcontent.cxx:274
bool isRootFolder() const
Definition: pkguri.hxx:81
const OUString & getScheme() const
Definition: pkguri.hxx:75
const OUString & getName() const
Definition: pkguri.hxx:69
const OUString & getParentUri() const
Definition: pkguri.hxx:60
const OUString & getPackage() const
Definition: pkguri.hxx:63
const OUString & getPath() const
Definition: pkguri.hxx:66
const OUString & getUri() const
Definition: pkguri.hxx:54
css::uno::Reference< css::ucb::XPersistentPropertySet > getAdditionalPropertySet(bool bCreate)
css::uno::Reference< css::ucb::XCommandInfo > getCommandInfo(const css::uno::Reference< css::ucb::XCommandEnvironment > &xEnv, bool bCache=true)
bool renameAdditionalPropertySet(const OUString &rOldKey, const OUString &rNewKey)
rtl::Reference< ContentProviderImplHelper > m_xProvider
bool exchange(const css::uno::Reference< css::ucb::XContentIdentifier > &rNewId)
css::uno::Reference< css::beans::XPropertySetInfo > getPropertySetInfo(const css::uno::Reference< css::ucb::XCommandEnvironment > &xEnv, bool bCache=true)
css::uno::Reference< css::ucb::XContentIdentifier > m_xIdentifier
css::uno::Reference< css::uno::XComponentContext > m_xContext
void notifyPropertiesChange(const css::uno::Sequence< css::beans::PropertyChangeEvent > &evt) const
int nCount
URL aURL
uno::Reference< deployment::XPackage > m_xPackage
float u
Reference< XInterface > xTarget
OUString aName
sal_Int64 n
tools::SvRef< SvBaseLink > xSink
Sequence< sal_Int8 > aSeq
#define CPPU_TYPE_REF(T)
constexpr OUStringLiteral aData
css::uno::Sequence< css::uno::Any > InitAnyPropertySequence(::std::initializer_list< ::std::pair< OUString, css::uno::Any > > vInit)
Type
css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType, Interface1 *p1)
Info
OUString encodeSegment(const OUString &rSegment)
Definition: urihelper.hxx:29
std::vector< ContentImplHelperRef > ContentRefList
void cancelCommandExecution(const uno::Any &rException, const uno::Reference< ucb::XCommandEnvironment > &xEnv)
#define ENCRYPTIONKEY_MODIFIED
Definition: pkgcontent.cxx:85
#define MEDIATYPE_MODIFIED
Definition: pkgcontent.cxx:82
XTYPEPROVIDER_COMMON_IMPL(Content)
#define NONE_MODIFIED
Definition: pkgcontent.cxx:81
#define COMPRESSED_MODIFIED
Definition: pkgcontent.cxx:83
#define ENCRYPTED_MODIFIED
Definition: pkgcontent.cxx:84
#define PACKAGE_ZIP_FOLDER_CONTENT_TYPE
Definition: pkgprovider.hxx:38
#define PACKAGE_FOLDER_CONTENT_TYPE
Definition: pkgprovider.hxx:34
#define PACKAGE_STREAM_CONTENT_TYPE
Definition: pkgprovider.hxx:36
#define PACKAGE_ZIP_STREAM_CONTENT_TYPE
Definition: pkgprovider.hxx:40
#define PACKAGE_URL_SCHEME_LENGTH
Definition: pkguri.hxx:30
uno::Sequence< beans::Property > m_aProps
css::uno::Sequence< css::ucb::ContentInfo > getCreatableContentsInfo(PackageUri const &rUri) const
Definition: pkgcontent.cxx:107
css::uno::Sequence< sal_Int8 > aEncryptionKey
Definition: pkgcontent.hxx:69
bool hasValue()
OUString aCommand
std::unique_ptr< char[]> aBuffer