Coverage Report

Created: 2026-06-30 11:14

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