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 static_cast< cppu::OWeakObject * >( this ),
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 static_cast< cppu::OWeakObject * >( this ),
428 -1 ) ),
429 Environment );
430 // Unreachable
431 }
432
433 if ( !aProperties.hasElements() )
434 {
436 uno::Any( lang::IllegalArgumentException(
437 "No properties!",
438 static_cast< cppu::OWeakObject * >( this ),
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 static_cast< cppu::OWeakObject * >( this ),
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 static_cast< cppu::OWeakObject * >( this ),
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 static_cast< cppu::OWeakObject * >( this ),
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 static_cast< cppu::OWeakObject * >( this ),
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 static_cast< cppu::OWeakObject * >( this ) ) ),
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 = static_cast< cppu::OWeakObject * >( this );
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 static_cast< cppu::OWeakObject * >( this ) );
987 }
988 else if ( rValue.Name == "IsDocument" )
989 {
990 // Read-only property!
991 aRetRange[ n ] <<= lang::IllegalAccessException(
992 "Property is read-only!",
993 static_cast< cppu::OWeakObject * >( this ) );
994 }
995 else if ( rValue.Name == "IsFolder" )
996 {
997 // Read-only property!
998 aRetRange[ n ] <<= lang::IllegalAccessException(
999 "Property is read-only!",
1000 static_cast< cppu::OWeakObject * >( this ) );
1001 }
1002 else if ( rValue.Name == "CreatableContentsInfo" )
1003 {
1004 // Read-only property!
1005 aRetRange[ n ] <<= lang::IllegalAccessException(
1006 "Property is read-only!",
1007 static_cast< cppu::OWeakObject * >( this ) );
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 static_cast< cppu::OWeakObject * >( this ) );
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 static_cast< cppu::OWeakObject * >( this ),
1046 -1 );
1047 }
1048 }
1049 else
1050 {
1051 aRetRange[ n ] <<=
1052 beans::IllegalTypeException(
1053 "Property value has wrong type!",
1054 static_cast< cppu::OWeakObject * >( this ) );
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 static_cast< cppu::OWeakObject * >( this ) );
1080 }
1081 }
1082 else if ( rValue.Name == "Size" )
1083 {
1084 // Read-only property!
1085 aRetRange[ n ] <<= lang::IllegalAccessException(
1086 "Property is read-only!",
1087 static_cast< cppu::OWeakObject * >( this ) );
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 static_cast< cppu::OWeakObject * >( this ) );
1114 }
1115 }
1116 else
1117 {
1118 aRetRange[ n ] <<= beans::UnknownPropertyException(
1119 "Compressed only supported by streams!",
1120 static_cast< cppu::OWeakObject * >( this ) );
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 static_cast< cppu::OWeakObject * >( this ) );
1148 }
1149 }
1150 else
1151 {
1152 aRetRange[ n ] <<= beans::UnknownPropertyException(
1153 "Encrypted only supported by streams!",
1154 static_cast< cppu::OWeakObject * >( this ) );
1155 }
1156 }
1157 else if ( rValue.Name == "HasEncryptedEntries" )
1158 {
1159 // Read-only property!
1160 aRetRange[ n ] <<= lang::IllegalAccessException(
1161 "Property is read-only!",
1162 static_cast< cppu::OWeakObject * >( this ) );
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 static_cast< cppu::OWeakObject * >( this ) );
1193 }
1194 }
1195 else
1196 {
1197 aRetRange[ n ] <<= beans::UnknownPropertyException(
1198 "EncryptionKey not supported by non-root folder!",
1199 static_cast< cppu::OWeakObject * >( this ) );
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 static_cast< cppu::OWeakObject * >( this ) );
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() + "/";
1263 aNewURL += ::ucb_impl::urihelper::encodeSegment( aNewTitle );
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 static_cast< cppu::OWeakObject * >( this ) );
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 static_cast< cppu::OWeakObject * >( this ),
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 static_cast< cppu::OWeakObject * >( this ),
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 static_cast< cppu::OWeakObject * >( this ) ) ),
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 static_cast< cppu::OWeakObject * >( this ),
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() + "_";
1542 aNew += OUString::number( ++nTry );
1543 aNewUri.setUri( aNew );
1544 }
1545 while ( hasData( aNewUri ) && ( nTry < 1000 ) );
1546
1547 if ( nTry == 1000 )
1548 {
1550 uno::Any(
1551 ucb::UnsupportedNameClashException(
1552 "Unable to resolve name clash!",
1553 static_cast< cppu::OWeakObject * >( this ),
1554 nNameClashResolve ) ),
1555 xEnv );
1556 // Unreachable
1557 }
1558 else
1559 {
1560 m_aProps.aTitle += "_";
1561 m_aProps.aTitle += OUString::number( nTry );
1562 }
1563 }
1564 break;
1565
1566 case ucb::NameClash::KEEP: // deprecated
1567 case ucb::NameClash::ASK:
1568 default:
1569 if ( hasData( aNewUri ) )
1570 {
1572 uno::Any(
1573 ucb::UnsupportedNameClashException(
1574 OUString(),
1575 static_cast< cppu::OWeakObject * >( this ),
1576 nNameClashResolve ) ),
1577 xEnv );
1578 // Unreachable
1579 }
1580 break;
1581 }
1582
1583 // Identifier changed?
1584 bool bNewId = ( m_aUri.getUri() != aNewUri.getUri() );
1585
1586 if ( bNewId )
1587 {
1588 m_xIdentifier = new ::ucbhelper::ContentIdentifier( aNewURL );
1589 m_aUri = aNewUri;
1590 }
1591
1592 if ( !storeData( xStream ) )
1593 {
1594 uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence(
1595 {
1596 {"Uri", uno::Any(m_xIdentifier->getContentIdentifier())}
1597 }));
1599 ucb::IOErrorCode_CANT_WRITE,
1600 aArgs,
1601 xEnv,
1602 "Cannot store persistent data!",
1603 this );
1604 // Unreachable
1605 }
1606
1608
1609 if ( bNewId )
1610 {
1611 // Take over correct default values from underlying packager...
1612 uno::Reference< container::XHierarchicalNameAccess > xXHierarchicalNameAccess;
1614 m_aUri,
1615 m_aProps,
1616 xXHierarchicalNameAccess );
1617
1618 aGuard.clear();
1619 inserted();
1620 }
1621}
1622
1623
1624void Content::destroy(
1625 bool bDeletePhysical,
1626 const uno::Reference< ucb::XCommandEnvironment >& xEnv )
1627{
1628 // @@@ take care about bDeletePhysical -> trashcan support
1629
1630 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1631
1632 uno::Reference< ucb::XContent > xThis = this;
1633
1634 // Persistent?
1635 if ( m_eState != PERSISTENT )
1636 {
1638 uno::Any( ucb::UnsupportedCommandException(
1639 "Not persistent!",
1640 static_cast< cppu::OWeakObject * >( this ) ) ),
1641 xEnv );
1642 // Unreachable
1643 }
1644
1645 m_eState = DEAD;
1646
1647 aGuard.clear();
1648 deleted();
1649
1650 if ( isFolder() )
1651 {
1652 // Process instantiated children...
1653
1654 ContentRefList aChildren;
1655 queryChildren( aChildren );
1656
1657 for ( auto& rChild : aChildren )
1658 {
1659 rChild->destroy( bDeletePhysical, xEnv );
1660 }
1661 }
1662}
1663
1664
1666 const ucb::TransferInfo& rInfo,
1667 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
1668{
1669 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1670
1671 // Persistent?
1672 if ( m_eState != PERSISTENT )
1673 {
1675 uno::Any( ucb::UnsupportedCommandException(
1676 "Not persistent!",
1677 static_cast< cppu::OWeakObject * >( this ) ) ),
1678 xEnv );
1679 // Unreachable
1680 }
1681
1682 // Is source a package content?
1683 if ( ( rInfo.SourceURL.isEmpty() ) ||
1684 ( rInfo.SourceURL.compareTo(
1685 m_aUri.getUri(), PACKAGE_URL_SCHEME_LENGTH + 3 ) != 0 ) )
1686 {
1688 uno::Any( ucb::InteractiveBadTransferURLException(
1689 OUString(),
1690 static_cast< cppu::OWeakObject * >( this ) ) ),
1691 xEnv );
1692 // Unreachable
1693 }
1694
1695 // Is source not a parent of me / not me?
1696 OUString aId = m_aUri.getParentUri() + "/";
1697
1698 if ( rInfo.SourceURL.getLength() <= aId.getLength() )
1699 {
1700 if ( aId.startsWith( rInfo.SourceURL ) )
1701 {
1702 uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence(
1703 {
1704 {"Uri", uno::Any(rInfo.SourceURL)}
1705 }));
1707 ucb::IOErrorCode_RECURSIVE,
1708 aArgs,
1709 xEnv,
1710 "Target is equal to or is a child of source!",
1711 this );
1712 // Unreachable
1713 }
1714 }
1715
1716
1717 // 0) Obtain content object for source.
1718
1719
1720 uno::Reference< ucb::XContentIdentifier > xId
1721 = new ::ucbhelper::ContentIdentifier( rInfo.SourceURL );
1722
1723 // Note: The static cast is okay here, because its sure that
1724 // m_xProvider is always the PackageContentProvider.
1726
1727 try
1728 {
1729 xSource = static_cast< Content * >(
1730 m_xProvider->queryContent( xId ).get() );
1731 }
1732 catch ( ucb::IllegalIdentifierException const & )
1733 {
1734 // queryContent
1735 }
1736
1737 if ( !xSource.is() )
1738 {
1739 uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence(
1740 {
1741 {"Uri", uno::Any(xId->getContentIdentifier())}
1742 }));
1744 ucb::IOErrorCode_CANT_READ,
1745 aArgs,
1746 xEnv,
1747 "Cannot instantiate source object!",
1748 this );
1749 // Unreachable
1750 }
1751
1752
1753 // 1) Create new child content.
1754
1755
1756 OUString aType = xSource->isFolder()
1757 ? getContentType( m_aUri.getScheme(), true )
1758 : getContentType( m_aUri.getScheme(), false );
1759 ucb::ContentInfo aContentInfo;
1760 aContentInfo.Type = aType;
1761 aContentInfo.Attributes = 0;
1762
1763 // Note: The static cast is okay here, because its sure that
1764 // createNewContent always creates a Content.
1766 = static_cast< Content * >( createNewContent( aContentInfo ).get() );
1767 if ( !xTarget.is() )
1768 {
1769 uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence(
1770 {
1771 {"Folder", uno::Any(aId)}
1772 }));
1774 ucb::IOErrorCode_CANT_CREATE,
1775 aArgs,
1776 xEnv,
1777 "XContentCreator::createNewContent failed!",
1778 this );
1779 // Unreachable
1780 }
1781
1782
1783 // 2) Copy data from source content to child content.
1784
1785
1786 uno::Sequence< beans::Property > aSourceProps
1787 = xSource->getPropertySetInfo( xEnv )->getProperties();
1788 sal_Int32 nCount = aSourceProps.getLength();
1789
1790 if ( nCount )
1791 {
1792 bool bHadTitle = rInfo.NewTitle.isEmpty();
1793
1794 // Get all source values.
1795 uno::Reference< sdbc::XRow > xRow
1796 = xSource->getPropertyValues( aSourceProps );
1797
1798 uno::Sequence< beans::PropertyValue > aValues( nCount );
1799 beans::PropertyValue* pValues = aValues.getArray();
1800
1801 const beans::Property* pProps = aSourceProps.getConstArray();
1802 for ( sal_Int32 n = 0; n < nCount; ++n )
1803 {
1804 const beans::Property& rProp = pProps[ n ];
1805 beans::PropertyValue& rValue = pValues[ n ];
1806
1807 rValue.Name = rProp.Name;
1808 rValue.Handle = rProp.Handle;
1809
1810 if ( !bHadTitle && rProp.Name == "Title" )
1811 {
1812 // Set new title instead of original.
1813 bHadTitle = true;
1814 rValue.Value <<= rInfo.NewTitle;
1815 }
1816 else
1817 rValue.Value
1818 = xRow->getObject( n + 1,
1819 uno::Reference<
1820 container::XNameAccess >() );
1821
1822 rValue.State = beans::PropertyState_DIRECT_VALUE;
1823
1824 if ( rProp.Attributes & beans::PropertyAttribute::REMOVABLE )
1825 {
1826 // Add Additional Core Property.
1827 try
1828 {
1829 xTarget->addProperty( rProp.Name,
1830 rProp.Attributes,
1831 rValue.Value );
1832 }
1833 catch ( beans::PropertyExistException const & )
1834 {
1835 }
1836 catch ( beans::IllegalTypeException const & )
1837 {
1838 }
1839 catch ( lang::IllegalArgumentException const & )
1840 {
1841 }
1842 }
1843 }
1844
1845 // Set target values.
1846 xTarget->setPropertyValues( aValues, xEnv );
1847 }
1848
1849
1850 // 3) Commit (insert) child.
1851
1852
1853 xTarget->insert( xSource->getInputStream(), rInfo.NameClash, xEnv );
1854
1855
1856 // 4) Transfer (copy) children of source.
1857
1858
1859 if ( xSource->isFolder() )
1860 {
1861 uno::Reference< container::XEnumeration > xIter
1862 = xSource->getIterator();
1863 if ( xIter.is() )
1864 {
1865 while ( xIter->hasMoreElements() )
1866 {
1867 try
1868 {
1869 uno::Reference< container::XNamed > xNamed;
1870 xIter->nextElement() >>= xNamed;
1871
1872 if ( !xNamed.is() )
1873 {
1874 OSL_FAIL( "Content::transfer - Got no XNamed!" );
1875 break;
1876 }
1877
1878 OUString aName = xNamed->getName();
1879
1880 if ( aName.isEmpty() )
1881 {
1882 OSL_FAIL( "Content::transfer - Empty name!" );
1883 break;
1884 }
1885
1886 OUString aChildId = xId->getContentIdentifier();
1887 if ( ( aChildId.lastIndexOf( '/' ) + 1 )
1888 != aChildId.getLength() )
1889 aChildId += "/";
1890
1891 aChildId += ::ucb_impl::urihelper::encodeSegment( aName );
1892
1893 ucb::TransferInfo aInfo;
1894 aInfo.MoveData = false;
1895 aInfo.NewTitle.clear();
1896 aInfo.SourceURL = aChildId;
1897 aInfo.NameClash = rInfo.NameClash;
1898
1899 // Transfer child to target.
1900 xTarget->transfer( aInfo, xEnv );
1901 }
1902 catch ( container::NoSuchElementException const & )
1903 {
1904 }
1905 catch ( lang::WrappedTargetException const & )
1906 {
1907 }
1908 }
1909 }
1910 }
1911
1912
1913 // 5) Destroy source ( when moving only ) .
1914
1915
1916 if ( !rInfo.MoveData )
1917 return;
1918
1919 xSource->destroy( true, xEnv );
1920
1921 // Remove all persistent data of source and its children.
1922 if ( !xSource->removeData() )
1923 {
1924 uno::Sequence<uno::Any> aArgs(comphelper::InitAnyPropertySequence(
1925 {
1926 {"Uri", uno::Any(xSource->m_xIdentifier->getContentIdentifier())}
1927 }));
1929 ucb::IOErrorCode_CANT_WRITE,
1930 aArgs,
1931 xEnv,
1932 "Cannot remove persistent data of source object!",
1933 this );
1934 // Unreachable
1935 }
1936
1937 // Remove own and all children's Additional Core Properties.
1938 xSource->removeAdditionalPropertySet();
1939}
1940
1941
1943 const uno::Reference< ucb::XContentIdentifier >& xNewId )
1944{
1945 if ( !xNewId.is() )
1946 return false;
1947
1948 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1949
1950 uno::Reference< ucb::XContent > xThis = this;
1951
1952 // Already persistent?
1953 if ( m_eState != PERSISTENT )
1954 {
1955 OSL_FAIL( "Content::exchangeIdentity - Not persistent!" );
1956 return false;
1957 }
1958
1959 // Exchange own identity.
1960
1961 // Fail, if a content with given id already exists.
1962 PackageUri aNewUri( xNewId->getContentIdentifier() );
1963 if ( !hasData( aNewUri ) )
1964 {
1965 OUString aOldURL = m_xIdentifier->getContentIdentifier();
1966
1967 aGuard.clear();
1968 if ( exchange( xNewId ) )
1969 {
1970 m_aUri = aNewUri;
1971 if ( isFolder() )
1972 {
1973 // Process instantiated children...
1974
1975 ContentRefList aChildren;
1976 queryChildren( aChildren );
1977
1978 for ( const auto& rChild : aChildren )
1979 {
1980 ContentRef xChild = rChild;
1981
1982 // Create new content identifier for the child...
1983 uno::Reference< ucb::XContentIdentifier > xOldChildId
1984 = xChild->getIdentifier();
1985 OUString aOldChildURL
1986 = xOldChildId->getContentIdentifier();
1987 OUString aNewChildURL
1988 = aOldChildURL.replaceAt(
1989 0,
1990 aOldURL.getLength(),
1991 xNewId->getContentIdentifier() );
1992 uno::Reference< ucb::XContentIdentifier > xNewChildId
1993 = new ::ucbhelper::ContentIdentifier( aNewChildURL );
1994
1995 if ( !xChild->exchangeIdentity( xNewChildId ) )
1996 return false;
1997 }
1998 }
1999 return true;
2000 }
2001 }
2002
2003 OSL_FAIL( "Content::exchangeIdentity - Panic! Cannot exchange identity!" );
2004 return false;
2005}
2006
2007
2009{
2010 // Obtain a list with a snapshot of all currently instantiated contents
2011 // from provider and extract the contents which are direct children
2012 // of this content.
2013
2014 ::ucbhelper::ContentRefList aAllContents;
2015 m_xProvider->queryExistingContents( aAllContents );
2016
2017 OUString aURL = m_xIdentifier->getContentIdentifier();
2018
2019 OSL_ENSURE( aURL.lastIndexOf( '/' ) != ( aURL.getLength() - 1 ),
2020 "Content::queryChildren - Invalid URL!" );
2021
2022 aURL += "/";
2023
2024 sal_Int32 nLen = aURL.getLength();
2025
2026 for ( const auto& rContent : aAllContents )
2027 {
2028 ::ucbhelper::ContentImplHelperRef xChild = rContent;
2029 OUString aChildURL
2030 = xChild->getIdentifier()->getContentIdentifier();
2031
2032 // Is aURL a prefix of aChildURL?
2033 if ( ( aChildURL.getLength() > nLen ) &&
2034 ( aChildURL.startsWith( aURL ) ) )
2035 {
2036 if ( aChildURL.indexOf( '/', nLen ) == -1 )
2037 {
2038 // No further slashes. It's a child!
2039 rChildren.emplace_back(
2040 static_cast< Content * >( xChild.get() ) );
2041 }
2042 }
2043 }
2044}
2045
2046
2047uno::Reference< container::XHierarchicalNameAccess > Content::getPackage(
2048 const PackageUri& rURI )
2049{
2050 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2051
2052 if ( rURI.getPackage() == m_aUri.getPackage() )
2053 {
2054 if ( !m_xPackage.is() )
2056
2057 return m_xPackage;
2058 }
2059
2060 return m_pProvider->createPackage( rURI );
2061}
2062
2063
2064uno::Reference< container::XHierarchicalNameAccess > Content::getPackage()
2065{
2066 return getPackage( m_aUri );
2067}
2068
2069
2070// static
2071bool Content::hasData(
2072 ContentProvider* pProvider,
2073 const PackageUri& rURI,
2074 uno::Reference< container::XHierarchicalNameAccess > & rxPackage )
2075{
2076 rxPackage = pProvider->createPackage( rURI );
2077 return rxPackage->hasByHierarchicalName( rURI.getPath() );
2078}
2079
2080
2081bool Content::hasData( const PackageUri& rURI )
2082{
2083 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2084
2085 uno::Reference< container::XHierarchicalNameAccess > xPackage;
2086 if ( rURI.getPackage() == m_aUri.getPackage() )
2087 {
2088 xPackage = getPackage();
2089 return xPackage->hasByHierarchicalName( rURI.getPath() );
2090 }
2091
2092 return hasData( m_pProvider, rURI, xPackage );
2093}
2094
2095
2096//static
2098 ContentProvider* pProvider,
2099 const PackageUri& rURI,
2100 ContentProperties& rProps,
2101 uno::Reference< container::XHierarchicalNameAccess > & rxPackage )
2102{
2103 rxPackage = pProvider->createPackage( rURI );
2104
2105 if ( rURI.isRootFolder() )
2106 {
2107 // Properties available only from package
2108 uno::Reference< beans::XPropertySet > xPackagePropSet(
2109 rxPackage, uno::UNO_QUERY );
2110
2111 OSL_ENSURE( xPackagePropSet.is(),
2112 "Content::loadData - "
2113 "Got no XPropertySet interface from package!" );
2114
2115 if ( xPackagePropSet.is() )
2116 {
2117 // HasEncryptedEntries (only available at root folder)
2118 try
2119 {
2120 uno::Any aHasEncryptedEntries
2121 = xPackagePropSet->getPropertyValue( "HasEncryptedEntries" );
2122 if ( !( aHasEncryptedEntries >>= rProps.bHasEncryptedEntries ) )
2123 {
2124 OSL_FAIL( "Content::loadData - "
2125 "Got no HasEncryptedEntries value!" );
2126 return false;
2127 }
2128 }
2129 catch ( beans::UnknownPropertyException const & )
2130 {
2131 OSL_FAIL( "Content::loadData - "
2132 "Got no HasEncryptedEntries value!" );
2133 return false;
2134 }
2135 catch ( lang::WrappedTargetException const & )
2136 {
2137 OSL_FAIL( "Content::loadData - "
2138 "Got no HasEncryptedEntries value!" );
2139 return false;
2140 }
2141 }
2142 }
2143
2144 if ( !rxPackage->hasByHierarchicalName( rURI.getPath() ) )
2145 return false;
2146
2147 try
2148 {
2149 uno::Any aEntry = rxPackage->getByHierarchicalName( rURI.getPath() );
2150 if ( aEntry.hasValue() )
2151 {
2152 uno::Reference< beans::XPropertySet > xPropSet;
2153 aEntry >>= xPropSet;
2154
2155 if ( !xPropSet.is() )
2156 {
2157 OSL_FAIL( "Content::loadData - Got no XPropertySet interface!" );
2158 return false;
2159 }
2160
2161 // Title
2162 rProps.aTitle = rURI.getName();
2163
2164 // MediaType
2165 try
2166 {
2167 uno::Any aMediaType = xPropSet->getPropertyValue("MediaType");
2168 if ( !( aMediaType >>= rProps.aMediaType ) )
2169 {
2170 OSL_FAIL( "Content::loadData - Got no MediaType value!" );
2171 return false;
2172 }
2173 }
2174 catch ( beans::UnknownPropertyException const & )
2175 {
2176 OSL_FAIL( "Content::loadData - Got no MediaType value!" );
2177 return false;
2178 }
2179 catch ( lang::WrappedTargetException const & )
2180 {
2181 OSL_FAIL( "Content::loadData - Got no MediaType value!" );
2182 return false;
2183 }
2184
2185 uno::Reference< container::XEnumerationAccess > xEnumAccess;
2186 aEntry >>= xEnumAccess;
2187
2188 // ContentType / IsFolder / IsDocument
2189 if ( xEnumAccess.is() )
2190 {
2191 // folder
2192 rProps.aContentType = getContentType( rURI.getScheme(), true );
2193 rProps.bIsDocument = false;
2194 rProps.bIsFolder = true;
2195 }
2196 else
2197 {
2198 // stream
2199 rProps.aContentType = getContentType( rURI.getScheme(), false );
2200 rProps.bIsDocument = true;
2201 rProps.bIsFolder = false;
2202 }
2203
2204 if ( rProps.bIsDocument )
2205 {
2206 // Size ( only available for streams )
2207 try
2208 {
2209 uno::Any aSize = xPropSet->getPropertyValue("Size");
2210 if ( !( aSize >>= rProps.nSize ) )
2211 {
2212 OSL_FAIL( "Content::loadData - Got no Size value!" );
2213 return false;
2214 }
2215 }
2216 catch ( beans::UnknownPropertyException const & )
2217 {
2218 OSL_FAIL( "Content::loadData - Got no Size value!" );
2219 return false;
2220 }
2221 catch ( lang::WrappedTargetException const & )
2222 {
2223 OSL_FAIL( "Content::loadData - Got no Size value!" );
2224 return false;
2225 }
2226
2227 // Compressed ( only available for streams )
2228 try
2229 {
2230 uno::Any aCompressed = xPropSet->getPropertyValue("Compressed");
2231 if ( !( aCompressed >>= rProps.bCompressed ) )
2232 {
2233 OSL_FAIL( "Content::loadData - Got no Compressed value!" );
2234 return false;
2235 }
2236 }
2237 catch ( beans::UnknownPropertyException const & )
2238 {
2239 OSL_FAIL( "Content::loadData - Got no Compressed value!" );
2240 return false;
2241 }
2242 catch ( lang::WrappedTargetException const & )
2243 {
2244 OSL_FAIL( "Content::loadData - Got no Compressed value!" );
2245 return false;
2246 }
2247
2248 // Encrypted ( only available for streams )
2249 try
2250 {
2251 uno::Any aEncrypted = xPropSet->getPropertyValue("Encrypted");
2252 if ( !( aEncrypted >>= rProps.bEncrypted ) )
2253 {
2254 OSL_FAIL( "Content::loadData - Got no Encrypted value!" );
2255 return false;
2256 }
2257 }
2258 catch ( beans::UnknownPropertyException const & )
2259 {
2260 OSL_FAIL( "Content::loadData - Got no Encrypted value!" );
2261 return false;
2262 }
2263 catch ( lang::WrappedTargetException const & )
2264 {
2265 OSL_FAIL( "Content::loadData - Got no Encrypted value!" );
2266 return false;
2267 }
2268 }
2269 return true;
2270 }
2271 }
2272 catch ( container::NoSuchElementException const & )
2273 {
2274 // getByHierarchicalName
2275 }
2276
2277 return false;
2278}
2279
2280
2282 const uno::Reference< ucb::XContentIdentifier >& xOldId,
2283 const uno::Reference< ucb::XContentIdentifier >& xNewId )
2284{
2285 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2286
2287 PackageUri aURI( xOldId->getContentIdentifier() );
2288 uno::Reference< container::XHierarchicalNameAccess > xNA = getPackage(
2289 aURI );
2290
2291 if ( !xNA->hasByHierarchicalName( aURI.getPath() ) )
2292 return;
2293
2294 try
2295 {
2296 uno::Any aEntry = xNA->getByHierarchicalName( aURI.getPath() );
2297 uno::Reference< container::XNamed > xNamed;
2298 aEntry >>= xNamed;
2299
2300 if ( !xNamed.is() )
2301 {
2302 OSL_FAIL( "Content::renameData - Got no XNamed interface!" );
2303 return;
2304 }
2305
2306 PackageUri aNewURI( xNewId->getContentIdentifier() );
2307
2308 // No success indicator!? No return value / exceptions specified.
2309 xNamed->setName( aNewURI.getName() );
2310 }
2311 catch ( container::NoSuchElementException const & )
2312 {
2313 // getByHierarchicalName
2314 }
2315}
2316
2317
2318bool Content::storeData( const uno::Reference< io::XInputStream >& xStream )
2319{
2320 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2321
2322 uno::Reference< container::XHierarchicalNameAccess > xNA = getPackage();
2323
2324 uno::Reference< beans::XPropertySet > xPackagePropSet(
2325 xNA, uno::UNO_QUERY );
2326 OSL_ENSURE( xPackagePropSet.is(),
2327 "Content::storeData - "
2328 "Got no XPropertySet interface from package!" );
2329
2330 if ( !xPackagePropSet.is() )
2331 return false;
2332
2334 {
2335 if ( m_aUri.isRootFolder() )
2336 {
2337 // Property available only from package and from streams (see below)
2338 try
2339 {
2340 xPackagePropSet->setPropertyValue(
2341 "EncryptionKey",
2343 m_nModifiedProps &= ~ENCRYPTIONKEY_MODIFIED;
2344 }
2345 catch ( beans::UnknownPropertyException const & )
2346 {
2347 // setPropertyValue
2348 }
2349 catch ( beans::PropertyVetoException const & )
2350 {
2351 // setPropertyValue
2352 }
2353 catch ( lang::IllegalArgumentException const & )
2354 {
2355 // setPropertyValue
2356 }
2357 catch ( lang::WrappedTargetException const & )
2358 {
2359 // setPropertyValue
2360 }
2361 }
2362 }
2363
2364 if ( !xNA->hasByHierarchicalName( m_aUri.getPath() ) )
2365 {
2366// if ( !bCreate )
2367// return sal_True;
2368
2369 try
2370 {
2371 // Create new resource...
2372 uno::Reference< lang::XSingleServiceFactory > xFac(
2373 xNA, uno::UNO_QUERY );
2374 if ( !xFac.is() )
2375 {
2376 OSL_FAIL( "Content::storeData - "
2377 "Got no XSingleServiceFactory interface!" );
2378 return false;
2379 }
2380
2381 uno::Sequence< uno::Any > aArgs{ uno::Any(isFolder()) };
2382
2383 uno::Reference< uno::XInterface > xNew
2384 = xFac->createInstanceWithArguments( aArgs );
2385
2386 if ( !xNew.is() )
2387 {
2388 OSL_FAIL( "Content::storeData - createInstance failed!" );
2389 return false;
2390 }
2391
2392 PackageUri aParentUri( getParentURL() );
2393 uno::Any aEntry
2394 = xNA->getByHierarchicalName( aParentUri.getPath() );
2395 uno::Reference< container::XNameContainer > xParentContainer;
2396 aEntry >>= xParentContainer;
2397
2398 if ( !xParentContainer.is() )
2399 {
2400 OSL_FAIL( "Content::storeData - "
2401 "Got no XNameContainer interface!" );
2402 return false;
2403 }
2404
2405 xParentContainer->insertByName( m_aProps.aTitle,
2406 uno::Any( xNew ) );
2407 }
2408 catch ( lang::IllegalArgumentException const & )
2409 {
2410 // insertByName
2411 OSL_FAIL( "Content::storeData - insertByName failed!" );
2412 return false;
2413 }
2414 catch ( uno::RuntimeException const & )
2415 {
2416 throw;
2417 }
2418 catch ( container::ElementExistException const & )
2419 {
2420 // insertByName
2421 OSL_FAIL( "Content::storeData - insertByName failed!" );
2422 return false;
2423 }
2424 catch ( lang::WrappedTargetException const & )
2425 {
2426 // insertByName
2427 OSL_FAIL( "Content::storeData - insertByName failed!" );
2428 return false;
2429 }
2430 catch ( container::NoSuchElementException const & )
2431 {
2432 // getByHierarchicalName
2433 OSL_FAIL( "Content::storeData - getByHierarchicalName failed!" );
2434 return false;
2435 }
2436 catch ( uno::Exception const & )
2437 {
2438 // createInstanceWithArguments
2439 OSL_FAIL( "Content::storeData - Error!" );
2440 return false;
2441 }
2442 }
2443
2444 if ( !xNA->hasByHierarchicalName( m_aUri.getPath() ) )
2445 return false;
2446
2447 try
2448 {
2449 uno::Reference< beans::XPropertySet > xPropSet;
2450 xNA->getByHierarchicalName( m_aUri.getPath() ) >>= xPropSet;
2451
2452 if ( !xPropSet.is() )
2453 {
2454 OSL_FAIL( "Content::storeData - Got no XPropertySet interface!" );
2455 return false;
2456 }
2457
2458
2459 // Store property values...
2460
2461
2463 {
2464 xPropSet->setPropertyValue(
2465 "MediaType",
2467 m_nModifiedProps &= ~MEDIATYPE_MODIFIED;
2468 }
2469
2471 {
2472 if ( !isFolder() )
2473 xPropSet->setPropertyValue(
2474 "Compressed",
2476
2477 m_nModifiedProps &= ~COMPRESSED_MODIFIED;
2478 }
2479
2481 {
2482 if ( !isFolder() )
2483 xPropSet->setPropertyValue(
2484 "Encrypted",
2486
2487 m_nModifiedProps &= ~ENCRYPTED_MODIFIED;
2488 }
2489
2491 {
2492 if ( !isFolder() )
2493 xPropSet->setPropertyValue(
2494 "EncryptionKey",
2496
2497 m_nModifiedProps &= ~ENCRYPTIONKEY_MODIFIED;
2498 }
2499
2500
2501 // Store data stream...
2502
2503
2504 if ( xStream.is() && !isFolder() )
2505 {
2506 uno::Reference< io::XActiveDataSink > xSink(
2507 xPropSet, uno::UNO_QUERY );
2508
2509 if ( !xSink.is() )
2510 {
2511 OSL_FAIL( "Content::storeData - "
2512 "Got no XActiveDataSink interface!" );
2513 return false;
2514 }
2515
2516 xSink->setInputStream( xStream );
2517 }
2518
2519 return true;
2520 }
2521 catch ( container::NoSuchElementException const & )
2522 {
2523 // getByHierarchicalName
2524 }
2525 catch ( beans::UnknownPropertyException const & )
2526 {
2527 // setPropertyValue
2528 }
2529 catch ( beans::PropertyVetoException const & )
2530 {
2531 // setPropertyValue
2532 }
2533 catch ( lang::IllegalArgumentException const & )
2534 {
2535 // setPropertyValue
2536 }
2537 catch ( lang::WrappedTargetException const & )
2538 {
2539 // setPropertyValue
2540 }
2541
2542 OSL_FAIL( "Content::storeData - Error!" );
2543 return false;
2544}
2545
2546
2548{
2549 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2550
2551 uno::Reference< container::XHierarchicalNameAccess > xNA = getPackage();
2552
2553 PackageUri aParentUri( getParentURL() );
2554 if ( !xNA->hasByHierarchicalName( aParentUri.getPath() ) )
2555 return false;
2556
2557 try
2558 {
2559 uno::Any aEntry = xNA->getByHierarchicalName( aParentUri.getPath() );
2560 uno::Reference< container::XNameContainer > xContainer;
2561 aEntry >>= xContainer;
2562
2563 if ( !xContainer.is() )
2564 {
2565 OSL_FAIL( "Content::removeData - "
2566 "Got no XNameContainer interface!" );
2567 return false;
2568 }
2569
2570 xContainer->removeByName( m_aUri.getName() );
2571 return true;
2572 }
2573 catch ( container::NoSuchElementException const & )
2574 {
2575 // getByHierarchicalName, removeByName
2576 }
2577 catch ( lang::WrappedTargetException const & )
2578 {
2579 // removeByName
2580 }
2581
2582 OSL_FAIL( "Content::removeData - Error!" );
2583 return false;
2584}
2585
2586
2588{
2589 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2590
2591 // Note: XChangesBatch is only implemented by the package itself, not
2592 // by the single entries. Maybe this has to change...
2593
2594 uno::Reference< container::XHierarchicalNameAccess > xNA = getPackage();
2595
2596 uno::Reference< util::XChangesBatch > xBatch( xNA, uno::UNO_QUERY );
2597 if ( !xBatch.is() )
2598 {
2599 OSL_FAIL( "Content::flushData - Got no XChangesBatch interface!" );
2600 return false;
2601 }
2602
2603 try
2604 {
2605 xBatch->commitChanges();
2606 return true;
2607 }
2608 catch ( lang::WrappedTargetException const & )
2609 {
2610 }
2611
2612 OSL_FAIL( "Content::flushData - Error!" );
2613 return false;
2614}
2615
2616
2617uno::Reference< io::XInputStream > Content::getInputStream()
2618{
2619 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2620
2621 uno::Reference< io::XInputStream > xStream;
2622 uno::Reference< container::XHierarchicalNameAccess > xNA = getPackage();
2623
2624 if ( !xNA->hasByHierarchicalName( m_aUri.getPath() ) )
2625 return xStream;
2626
2627 try
2628 {
2629 uno::Any aEntry = xNA->getByHierarchicalName( m_aUri.getPath() );
2630 uno::Reference< io::XActiveDataSink > xSink;
2631 aEntry >>= xSink;
2632
2633 if ( !xSink.is() )
2634 {
2635 OSL_FAIL( "Content::getInputStream - "
2636 "Got no XActiveDataSink interface!" );
2637 return xStream;
2638 }
2639
2640 xStream = xSink->getInputStream();
2641
2642 OSL_ENSURE( xStream.is(),
2643 "Content::getInputStream - Got no stream!" );
2644 }
2645 catch ( container::NoSuchElementException const & )
2646 {
2647 // getByHierarchicalName
2648 }
2649
2650 return xStream;
2651}
2652
2653
2654uno::Reference< container::XEnumeration > Content::getIterator()
2655{
2656 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2657
2658 uno::Reference< container::XEnumeration > xIter;
2659 uno::Reference< container::XHierarchicalNameAccess > xNA = getPackage();
2660
2661 if ( !xNA->hasByHierarchicalName( m_aUri.getPath() ) )
2662 return xIter;
2663
2664 try
2665 {
2666 uno::Any aEntry = xNA->getByHierarchicalName( m_aUri.getPath() );
2667 uno::Reference< container::XEnumerationAccess > xIterFac;
2668 aEntry >>= xIterFac;
2669
2670 if ( !xIterFac.is() )
2671 {
2672 OSL_FAIL( "Content::getIterator - "
2673 "Got no XEnumerationAccess interface!" );
2674 return xIter;
2675 }
2676
2677 xIter = xIterFac->createEnumeration();
2678
2679 OSL_ENSURE( xIter.is(),
2680 "Content::getIterator - Got no iterator!" );
2681 }
2682 catch ( container::NoSuchElementException const & )
2683 {
2684 // getByHierarchicalName
2685 }
2686
2687 return xIter;
2688}
2689
2690/* 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