Coverage Report

Created: 2026-03-31 11:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/ucbhelper/source/provider/contenthelper.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
#include <sal/config.h>
21
22
#include <com/sun/star/lang/NoSupportException.hpp>
23
#include <com/sun/star/ucb/ContentAction.hpp>
24
#include <com/sun/star/ucb/IllegalIdentifierException.hpp>
25
#include <com/sun/star/ucb/XPersistentPropertySet.hpp>
26
#include <com/sun/star/beans/IllegalTypeException.hpp>
27
#include <com/sun/star/beans/NotRemoveableException.hpp>
28
#include <com/sun/star/beans/PropertyAttribute.hpp>
29
#include <com/sun/star/beans/PropertyExistException.hpp>
30
#include <com/sun/star/beans/PropertySetInfoChange.hpp>
31
#include <comphelper/interfacecontainer3.hxx>
32
#include <cppuhelper/interfacecontainer.hxx>
33
#include <cppuhelper/supportsservice.hxx>
34
#include <cppuhelper/queryinterface.hxx>
35
#include <ucbhelper/contenthelper.hxx>
36
#include <ucbhelper/contentidentifier.hxx>
37
#include "contentinfo.hxx"
38
#include <ucbhelper/providerhelper.hxx>
39
#include <ucbhelper/macros.hxx>
40
41
#include <osl/diagnose.h>
42
#include <osl/mutex.hxx>
43
#include <rtl/ref.hxx>
44
45
#include <unordered_map>
46
#include <utility>
47
48
using namespace com::sun::star;
49
50
namespace ucbhelper_impl
51
{
52
53
namespace {
54
55
class PropertyEventSequence
56
{
57
    uno::Sequence< beans::PropertyChangeEvent > m_aSeq;
58
    sal_uInt32                                  m_nPos;
59
60
public:
61
    explicit PropertyEventSequence( sal_uInt32 nSize )
62
0
    : m_aSeq( nSize ), m_nPos( 0 ) {};
63
64
    void append( const beans::PropertyChangeEvent& rEvt )
65
0
    { m_aSeq.getArray()[ m_nPos ] = rEvt; ++m_nPos; }
66
67
    const uno::Sequence< beans::PropertyChangeEvent >& getEvents()
68
0
    { m_aSeq.realloc( m_nPos ); return m_aSeq; }
69
};
70
71
}
72
73
typedef void* XPropertiesChangeListenerPtr; // -> Compiler problems!
74
75
namespace {
76
77
struct equalPtr
78
{
79
    bool operator()( const XPropertiesChangeListenerPtr& rp1,
80
                     const XPropertiesChangeListenerPtr& rp2 ) const
81
0
    {
82
0
        return ( rp1 == rp2 );
83
0
    }
84
};
85
86
struct hashPtr
87
{
88
    size_t operator()( const XPropertiesChangeListenerPtr& rp ) const
89
0
    {
90
0
        return reinterpret_cast<size_t>(rp);
91
0
    }
92
};
93
94
}
95
96
typedef std::unordered_map
97
<
98
    XPropertiesChangeListenerPtr,
99
    PropertyEventSequence,
100
    hashPtr,
101
    equalPtr
102
>
103
PropertiesEventListenerMap;
104
105
typedef cppu::OMultiTypeInterfaceContainerHelperVar<OUString>
106
    PropertyChangeListeners;
107
108
struct ContentImplHelper_Impl
109
{
110
    rtl::Reference< ::ucbhelper::PropertySetInfo >      m_xPropSetInfo;
111
    rtl::Reference< ::ucbhelper::CommandProcessorInfo > m_xCommandsInfo;
112
    std::unique_ptr<cppu::OInterfaceContainerHelper>    m_pDisposeEventListeners;
113
    std::unique_ptr<comphelper::OInterfaceContainerHelper3<css::ucb::XContentEventListener>>
114
                                                        m_pContentEventListeners;
115
    std::unique_ptr<comphelper::OInterfaceContainerHelper3<beans::XPropertySetInfoChangeListener>>
116
                                                        m_pPropSetChangeListeners;
117
    std::unique_ptr<cppu::OInterfaceContainerHelper>    m_pCommandChangeListeners;
118
    std::unique_ptr<PropertyChangeListeners>            m_pPropertyChangeListeners;
119
};
120
121
} // namespace ucbhelper_impl
122
123
using namespace ucbhelper_impl;
124
125
namespace ucbhelper {
126
127
ContentImplHelper::ContentImplHelper(
128
            uno::Reference< uno::XComponentContext > xContext,
129
            rtl::Reference< ContentProviderImplHelper > xProvider,
130
            uno::Reference<
131
            css::ucb::XContentIdentifier > Identifier )
132
0
: m_pImpl( new ContentImplHelper_Impl ),
133
0
  m_xContext(std::move( xContext )),
134
0
  m_xIdentifier(std::move( Identifier )),
135
0
  m_xProvider(std::move( xProvider )),
136
0
  m_nCommandId( 0 )
137
0
{
138
0
}
139
140
// virtual
141
ContentImplHelper::~ContentImplHelper()
142
0
{
143
0
}
144
145
void SAL_CALL ContentImplHelper::release()
146
    noexcept
147
0
{
148
    // #144882# - Call to OWeakObject::release may destroy m_xProvider.
149
    //            Prevent this.
150
0
    rtl::Reference< ContentProviderImplHelper > xKeepProviderAlive(
151
0
        m_xProvider );
152
153
0
    osl::MutexGuard aGuard( m_xProvider->m_aMutex );
154
0
    OWeakObject::release();
155
0
}
156
157
uno::Any SAL_CALL ContentImplHelper::queryInterface( const uno::Type & rType )
158
0
{
159
0
    css::uno::Any aRet = cppu::queryInterface( rType,
160
0
            static_cast< lang::XTypeProvider * >(this),
161
0
            static_cast< lang::XServiceInfo * >(this),
162
0
            static_cast< lang::XComponent * >(this),
163
0
            static_cast< css::ucb::XContent * >(this),
164
0
            static_cast< css::ucb::XCommandProcessor * >(this),
165
0
            static_cast< beans::XPropertiesChangeNotifier * >(this),
166
0
            static_cast< css::ucb::XCommandInfoChangeNotifier * >(this),
167
0
            static_cast< beans::XPropertyContainer * >(this),
168
0
            static_cast< beans::XPropertySetInfoChangeNotifier * >(this),
169
0
            static_cast< container::XChild * >(this));
170
0
    return aRet.hasValue() ? aRet : cppu::OWeakObject::queryInterface( rType );
171
0
}
172
173
XTYPEPROVIDER_IMPL_10( ContentImplHelper,
174
                       lang::XTypeProvider,
175
                       lang::XServiceInfo,
176
                       lang::XComponent,
177
                       css::ucb::XContent,
178
                       css::ucb::XCommandProcessor,
179
                       beans::XPropertiesChangeNotifier,
180
                       css::ucb::XCommandInfoChangeNotifier,
181
                       beans::XPropertyContainer,
182
                       beans::XPropertySetInfoChangeNotifier,
183
                       container::XChild );
184
185
// virtual
186
sal_Bool SAL_CALL ContentImplHelper::supportsService(
187
                                            const OUString& ServiceName )
188
0
{
189
0
    return cppu::supportsService(this, ServiceName);
190
0
}
191
192
// virtual
193
void SAL_CALL ContentImplHelper::dispose()
194
0
{
195
0
    osl::MutexGuard aGuard( m_aMutex );
196
197
0
    if ( m_pImpl->m_pDisposeEventListeners &&
198
0
         m_pImpl->m_pDisposeEventListeners->getLength() )
199
0
    {
200
0
        lang::EventObject aEvt;
201
0
        aEvt.Source = static_cast< lang::XComponent * >( this );
202
0
        m_pImpl->m_pDisposeEventListeners->disposeAndClear( aEvt );
203
0
    }
204
205
0
    if ( m_pImpl->m_pContentEventListeners &&
206
0
         m_pImpl->m_pContentEventListeners->getLength() )
207
0
    {
208
0
        lang::EventObject aEvt;
209
0
        aEvt.Source = static_cast< css::ucb::XContent * >( this );
210
0
        m_pImpl->m_pContentEventListeners->disposeAndClear( aEvt );
211
0
    }
212
213
0
    if ( m_pImpl->m_pPropSetChangeListeners &&
214
0
         m_pImpl->m_pPropSetChangeListeners->getLength() )
215
0
    {
216
0
        lang::EventObject aEvt;
217
0
        aEvt.Source
218
0
            = static_cast< beans::XPropertySetInfoChangeNotifier * >( this );
219
0
        m_pImpl->m_pPropSetChangeListeners->disposeAndClear( aEvt );
220
0
    }
221
222
0
    if ( m_pImpl->m_pCommandChangeListeners &&
223
0
         m_pImpl->m_pCommandChangeListeners->getLength() )
224
0
    {
225
0
        lang::EventObject aEvt;
226
0
        aEvt.Source = static_cast<  css::ucb::XCommandInfoChangeNotifier * >( this );
227
0
        m_pImpl->m_pCommandChangeListeners->disposeAndClear( aEvt );
228
0
    }
229
230
0
    if ( m_pImpl->m_pPropertyChangeListeners )
231
0
    {
232
0
        lang::EventObject aEvt;
233
0
        aEvt.Source
234
0
            = static_cast< beans::XPropertiesChangeNotifier * >( this );
235
0
        m_pImpl->m_pPropertyChangeListeners->disposeAndClear( aEvt );
236
0
    }
237
0
}
238
239
// virtual
240
void SAL_CALL ContentImplHelper::addEventListener(
241
        const uno::Reference< lang::XEventListener >& Listener )
242
0
{
243
0
    osl::MutexGuard aGuard( m_aMutex );
244
245
0
    if ( !m_pImpl->m_pDisposeEventListeners )
246
0
        m_pImpl->m_pDisposeEventListeners.reset(
247
0
            new cppu::OInterfaceContainerHelper( m_aMutex ));
248
249
0
    m_pImpl->m_pDisposeEventListeners->addInterface( Listener );
250
0
}
251
252
// virtual
253
void SAL_CALL ContentImplHelper::removeEventListener(
254
        const uno::Reference< lang::XEventListener >& Listener )
255
0
{
256
0
    osl::MutexGuard aGuard( m_aMutex );
257
258
0
    if ( m_pImpl->m_pDisposeEventListeners )
259
0
        m_pImpl->m_pDisposeEventListeners->removeInterface( Listener );
260
0
}
261
262
// virtual
263
uno::Reference< css::ucb::XContentIdentifier > SAL_CALL
264
ContentImplHelper::getIdentifier()
265
0
{
266
0
    return m_xIdentifier;
267
0
}
268
269
// virtual
270
void SAL_CALL ContentImplHelper::addContentEventListener(
271
        const uno::Reference< css::ucb::XContentEventListener >& Listener )
272
0
{
273
0
    osl::MutexGuard aGuard( m_aMutex );
274
275
0
    if ( !m_pImpl->m_pContentEventListeners )
276
0
        m_pImpl->m_pContentEventListeners.reset(
277
0
            new comphelper::OInterfaceContainerHelper3<css::ucb::XContentEventListener>( m_aMutex ));
278
279
0
    m_pImpl->m_pContentEventListeners->addInterface( Listener );
280
0
}
281
282
// virtual
283
void SAL_CALL ContentImplHelper::removeContentEventListener(
284
        const uno::Reference< css::ucb::XContentEventListener >& Listener )
285
0
{
286
0
    osl::MutexGuard aGuard( m_aMutex );
287
288
0
    if ( m_pImpl->m_pContentEventListeners )
289
0
        m_pImpl->m_pContentEventListeners->removeInterface( Listener );
290
0
}
291
292
// virtual
293
sal_Int32 SAL_CALL ContentImplHelper::createCommandIdentifier()
294
0
{
295
0
    osl::MutexGuard aGuard( m_aMutex );
296
297
    // Just increase counter on every call to generate an identifier.
298
0
    return ++m_nCommandId;
299
0
}
300
301
// virtual
302
void SAL_CALL ContentImplHelper::addPropertiesChangeListener(
303
        const uno::Sequence< OUString >& PropertyNames,
304
        const uno::Reference< beans::XPropertiesChangeListener >& Listener )
305
0
{
306
0
    osl::MutexGuard aGuard( m_aMutex );
307
308
0
    if ( !m_pImpl->m_pPropertyChangeListeners )
309
0
        m_pImpl->m_pPropertyChangeListeners.reset(
310
0
            new PropertyChangeListeners( m_aMutex ));
311
312
0
    if ( !PropertyNames.hasElements() )
313
0
    {
314
        // Note: An empty sequence means a listener for "all" properties.
315
0
        m_pImpl->m_pPropertyChangeListeners->addInterface(
316
0
            OUString(), Listener );
317
0
    }
318
0
    else
319
0
    {
320
0
        for ( const OUString& rName : PropertyNames )
321
0
        {
322
0
            if ( !rName.isEmpty() )
323
0
                m_pImpl->m_pPropertyChangeListeners->addInterface(
324
0
                    rName, Listener );
325
0
        }
326
0
    }
327
0
}
328
329
// virtual
330
void SAL_CALL ContentImplHelper::removePropertiesChangeListener(
331
        const uno::Sequence< OUString >& PropertyNames,
332
        const uno::Reference< beans::XPropertiesChangeListener >& Listener )
333
0
{
334
0
    osl::MutexGuard aGuard( m_aMutex );
335
336
0
    if ( !m_pImpl->m_pPropertyChangeListeners )
337
0
        return;
338
339
0
    if ( !PropertyNames.hasElements() )
340
0
    {
341
        // Note: An empty sequence means a listener for "all" properties.
342
0
        m_pImpl->m_pPropertyChangeListeners->removeInterface(
343
0
            OUString(), Listener );
344
0
    }
345
0
    else
346
0
    {
347
0
        for ( const OUString& rName : PropertyNames )
348
0
        {
349
0
            if ( !rName.isEmpty() )
350
0
                m_pImpl->m_pPropertyChangeListeners->removeInterface(
351
0
                    rName, Listener );
352
0
        }
353
0
    }
354
0
}
355
356
// virtual
357
void SAL_CALL ContentImplHelper::addCommandInfoChangeListener(
358
        const uno::Reference< css::ucb::XCommandInfoChangeListener >& Listener )
359
0
{
360
0
    osl::MutexGuard aGuard( m_aMutex );
361
362
0
    if ( !m_pImpl->m_pCommandChangeListeners )
363
0
        m_pImpl->m_pCommandChangeListeners.reset(
364
0
            new cppu::OInterfaceContainerHelper( m_aMutex ));
365
366
0
    m_pImpl->m_pCommandChangeListeners->addInterface( Listener );
367
0
}
368
369
// virtual
370
void SAL_CALL ContentImplHelper::removeCommandInfoChangeListener(
371
        const uno::Reference< css::ucb::XCommandInfoChangeListener >& Listener )
372
0
{
373
0
    osl::MutexGuard aGuard( m_aMutex );
374
375
0
    if ( m_pImpl->m_pCommandChangeListeners )
376
0
        m_pImpl->m_pCommandChangeListeners->removeInterface( Listener );
377
0
}
378
379
// virtual
380
void SAL_CALL ContentImplHelper::addProperty(
381
        const OUString& Name,
382
        sal_Int16 Attributes,
383
        const uno::Any& DefaultValue )
384
0
{
385
0
    osl::MutexGuard aGuard( m_aMutex );
386
387
    // Make sure a property with the requested name does not already
388
    // exist in dynamic and static(!) properties.
389
390
    // @@@ Need real command environment here, but where to get it from?
391
    //     XPropertyContainer interface should be replaced by
392
    //     XCommandProcessor commands!
393
0
    uno::Reference< css::ucb::XCommandEnvironment > xEnv;
394
395
0
    if ( getPropertySetInfo( xEnv )->hasPropertyByName( Name ) )
396
0
    {
397
        // Property does already exist.
398
0
        throw beans::PropertyExistException();
399
0
    }
400
401
    // Add a new dynamic property.
402
    // Open/create persistent property set.
403
0
    uno::Reference< css::ucb::XPersistentPropertySet > xSet(
404
0
                                    getAdditionalPropertySet( true ) );
405
406
0
    OSL_ENSURE( xSet.is(),
407
0
                "ContentImplHelper::addProperty - No property set!" );
408
409
0
    if ( !xSet.is() )
410
0
        return;
411
412
0
    uno::Reference< beans::XPropertyContainer > xContainer(
413
0
        xSet, uno::UNO_QUERY );
414
415
0
    OSL_ENSURE(
416
0
        xContainer.is(),
417
0
        "ContentImplHelper::addProperty - No property container!" );
418
419
0
    if ( !xContainer.is() )
420
0
        return;
421
422
    // Property is always removable.
423
0
    Attributes |= beans::PropertyAttribute::REMOVABLE;
424
425
0
    try
426
0
    {
427
0
        xContainer->addProperty( Name, Attributes, DefaultValue );
428
0
    }
429
0
    catch ( beans::PropertyExistException const & )
430
0
    {
431
0
        OSL_FAIL( "ContentImplHelper::addProperty - Exists!" );
432
0
        throw;
433
0
    }
434
0
    catch ( beans::IllegalTypeException const & )
435
0
    {
436
0
        OSL_FAIL( "ContentImplHelper::addProperty - Wrong Type!" );
437
0
        throw;
438
0
    }
439
0
    catch ( lang::IllegalArgumentException const & )
440
0
    {
441
0
        OSL_FAIL( "ContentImplHelper::addProperty - Illegal Arg!" );
442
0
        throw;
443
0
    }
444
445
    // Success!
446
447
0
    if ( m_pImpl->m_xPropSetInfo.is() )
448
0
    {
449
        // Info cached in propertyset info is invalid now!
450
0
        m_pImpl->m_xPropSetInfo->reset();
451
0
    }
452
453
    // Notify propertyset info change listeners.
454
0
    if ( m_pImpl->m_pPropSetChangeListeners &&
455
0
         m_pImpl->m_pPropSetChangeListeners->getLength() )
456
0
    {
457
0
        beans::PropertySetInfoChangeEvent evt(
458
0
                    getXWeak(),
459
0
                    Name,
460
0
                    -1, // No handle available
461
0
                    beans::PropertySetInfoChange::PROPERTY_INSERTED );
462
0
        notifyPropertySetInfoChange( evt );
463
0
    }
464
0
}
465
466
// virtual
467
void SAL_CALL ContentImplHelper::removeProperty( const OUString& Name )
468
0
{
469
0
    osl::MutexGuard aGuard( m_aMutex );
470
471
0
    try
472
0
    {
473
        // @@@ Need real command environment here, but where to get it from?
474
        //     XPropertyContainer interface should be replaced by
475
        //     XCommandProcessor commands!
476
0
        uno::Reference< css::ucb::XCommandEnvironment > xEnv;
477
478
0
        beans::Property aProp
479
0
            = getPropertySetInfo( xEnv )->getPropertyByName( Name );
480
481
0
        if ( !( aProp.Attributes & beans::PropertyAttribute::REMOVABLE ) )
482
0
        {
483
            // Not removable!
484
0
            throw beans::NotRemoveableException();
485
0
        }
486
0
    }
487
0
    catch ( beans::UnknownPropertyException const & )
488
0
    {
489
0
        OSL_FAIL( "ContentImplHelper::removeProperty - Unknown!" );
490
0
        throw;
491
0
    }
492
493
    // Try to remove property from dynamic property set.
494
    // Open persistent property set, if exists.
495
0
    uno::Reference< css::ucb::XPersistentPropertySet > xSet(
496
0
        getAdditionalPropertySet( false ) );
497
0
    if ( !xSet.is() )
498
0
        return;
499
500
0
    uno::Reference< beans::XPropertyContainer > xContainer(
501
0
        xSet, uno::UNO_QUERY );
502
503
0
    OSL_ENSURE(
504
0
        xContainer.is(),
505
0
        "ContentImplHelper::removeProperty - No property container!" );
506
507
0
    if ( !xContainer.is() )
508
0
        return;
509
510
0
    try
511
0
    {
512
0
        xContainer->removeProperty( Name );
513
0
    }
514
0
    catch ( beans::UnknownPropertyException const & )
515
0
    {
516
0
        OSL_FAIL( "ContentImplHelper::removeProperty - Unknown!" );
517
0
        throw;
518
0
    }
519
0
    catch ( beans::NotRemoveableException const & )
520
0
    {
521
0
        OSL_FAIL(
522
0
            "ContentImplHelper::removeProperty - Unremovable!" );
523
0
        throw;
524
0
    }
525
526
0
    xContainer = nullptr;
527
528
    // Success!
529
530
0
    if ( !xSet->getPropertySetInfo()->getProperties().hasElements() )
531
0
    {
532
        // Remove empty propertyset from registry.
533
0
        uno::Reference< css::ucb::XPropertySetRegistry >
534
0
            xReg = xSet->getRegistry();
535
0
        if ( xReg.is() )
536
0
        {
537
0
            OUString aKey( xSet->getKey() );
538
0
            xSet = nullptr;
539
0
            xReg->removePropertySet( aKey );
540
0
        }
541
0
    }
542
543
0
    if ( m_pImpl->m_xPropSetInfo.is() )
544
0
    {
545
        // Info cached in propertyset info is invalid now!
546
0
        m_pImpl->m_xPropSetInfo->reset();
547
0
    }
548
549
    // Notify propertyset info change listeners.
550
0
    if ( m_pImpl->m_pPropSetChangeListeners &&
551
0
         m_pImpl->m_pPropSetChangeListeners->getLength() )
552
0
    {
553
0
        beans::PropertySetInfoChangeEvent evt(
554
0
                    getXWeak(),
555
0
                    Name,
556
0
                    -1, // No handle available
557
0
                    beans::PropertySetInfoChange::PROPERTY_REMOVED );
558
0
        notifyPropertySetInfoChange( evt );
559
0
    }
560
0
}
561
562
// virtual
563
void SAL_CALL ContentImplHelper::addPropertySetInfoChangeListener(
564
        const uno::Reference< beans::XPropertySetInfoChangeListener >& Listener )
565
0
{
566
0
    osl::MutexGuard aGuard( m_aMutex );
567
568
0
    if ( !m_pImpl->m_pPropSetChangeListeners )
569
0
        m_pImpl->m_pPropSetChangeListeners.reset(
570
0
            new comphelper::OInterfaceContainerHelper3<beans::XPropertySetInfoChangeListener>( m_aMutex ));
571
572
0
    m_pImpl->m_pPropSetChangeListeners->addInterface( Listener );
573
0
}
574
575
// virtual
576
void SAL_CALL ContentImplHelper::removePropertySetInfoChangeListener(
577
        const uno::Reference< beans::XPropertySetInfoChangeListener >& Listener )
578
0
{
579
0
    osl::MutexGuard aGuard( m_aMutex );
580
581
0
    if ( m_pImpl->m_pPropSetChangeListeners )
582
0
        m_pImpl->m_pPropSetChangeListeners->removeInterface( Listener );
583
0
}
584
585
// virtual
586
uno::Reference< uno::XInterface > SAL_CALL ContentImplHelper::getParent()
587
0
{
588
0
    uno::Reference< uno::XInterface > xParent;
589
0
    OUString aURL = getParentURL();
590
591
0
    if ( !aURL.isEmpty() )
592
0
    {
593
0
        uno::Reference< css::ucb::XContentIdentifier > xId(
594
0
            new ContentIdentifier( aURL ) );
595
0
        try
596
0
        {
597
0
            xParent.set( m_xProvider->queryContent( xId ) );
598
0
        }
599
0
        catch ( css::ucb::IllegalIdentifierException const & )
600
0
        {
601
0
        }
602
0
    }
603
604
0
    return xParent;
605
0
}
606
607
// virtual
608
void SAL_CALL ContentImplHelper::setParent(
609
                                    const uno::Reference< uno::XInterface >& )
610
0
{
611
0
    throw lang::NoSupportException();
612
0
}
613
614
uno::Reference< css::ucb::XPersistentPropertySet >
615
ContentImplHelper::getAdditionalPropertySet( bool bCreate )
616
0
{
617
    // Get propertyset from provider.
618
0
    return m_xProvider->getAdditionalPropertySet(
619
0
                            m_xIdentifier->getContentIdentifier(), bCreate );
620
0
}
621
622
bool ContentImplHelper::renameAdditionalPropertySet(
623
    const OUString& rOldKey,
624
    const OUString& rNewKey )
625
0
{
626
0
    return m_xProvider->renameAdditionalPropertySet(
627
0
                                            rOldKey, rNewKey, true/*bRecursive*/ );
628
0
}
629
630
bool ContentImplHelper::copyAdditionalPropertySet(
631
    const OUString& rSourceKey,
632
    const OUString& rTargetKey )
633
0
{
634
0
    return m_xProvider->copyAdditionalPropertySet(
635
0
                                        rSourceKey, rTargetKey, true/*bRecursive*/ );
636
0
}
637
638
bool ContentImplHelper::removeAdditionalPropertySet()
639
0
{
640
0
    return m_xProvider->removeAdditionalPropertySet(
641
0
                    m_xIdentifier->getContentIdentifier(), true/*bRecursive*/ );
642
0
}
643
644
void ContentImplHelper::notifyPropertiesChange(
645
    const uno::Sequence< beans::PropertyChangeEvent >& evt ) const
646
0
{
647
0
    if ( !m_pImpl->m_pPropertyChangeListeners )
648
0
        return;
649
650
0
    sal_Int32 nCount = evt.getLength();
651
0
    if ( !nCount )
652
0
        return;
653
654
    // First, notify listeners interested in changes of every property.
655
0
    cppu::OInterfaceContainerHelper* pAllPropsContainer
656
0
        = m_pImpl->m_pPropertyChangeListeners->getContainer(
657
0
            OUString() );
658
0
    if ( pAllPropsContainer )
659
0
    {
660
0
        cppu::OInterfaceIteratorHelper aIter( *pAllPropsContainer );
661
0
        while ( aIter.hasMoreElements() )
662
0
        {
663
            // Propagate event.
664
0
            static_cast< beans::XPropertiesChangeListener* >(
665
0
                aIter.next())->propertiesChange( evt );
666
0
        }
667
0
    }
668
669
0
    PropertiesEventListenerMap aListeners;
670
671
0
    for ( const beans::PropertyChangeEvent& rEvent : evt )
672
0
    {
673
0
        const OUString& rName = rEvent.PropertyName;
674
675
0
        cppu::OInterfaceContainerHelper* pPropsContainer
676
0
            = m_pImpl->m_pPropertyChangeListeners->getContainer( rName );
677
0
        if ( pPropsContainer )
678
0
        {
679
0
            cppu::OInterfaceIteratorHelper aIter( *pPropsContainer );
680
0
            while ( aIter.hasMoreElements() )
681
0
            {
682
0
                PropertyEventSequence* p = nullptr;
683
684
0
                beans::XPropertiesChangeListener* pListener =
685
0
                    static_cast< beans::XPropertiesChangeListener * >(
686
0
                                                        aIter.next() );
687
0
                PropertiesEventListenerMap::iterator it =
688
0
                        aListeners.find( pListener );
689
0
                if ( it == aListeners.end() )
690
0
                {
691
                    // Not in map - create and insert new entry.
692
0
                    p = &aListeners.emplace( pListener, PropertyEventSequence(nCount)).first->second;
693
0
                }
694
0
                else
695
0
                    p = &it->second;
696
697
0
                if ( p )
698
0
                    p->append( rEvent );
699
0
            }
700
0
        }
701
0
    }
702
703
    // Notify listeners.
704
0
    PropertiesEventListenerMap::iterator it = aListeners.begin();
705
0
    while ( !aListeners.empty() )
706
0
    {
707
0
        beans::XPropertiesChangeListener* pListener =
708
0
            static_cast< beans::XPropertiesChangeListener * >( (*it).first );
709
0
        PropertyEventSequence pSeq = std::move(it->second);
710
711
        // Remove current element.
712
0
        aListeners.erase( it );
713
714
        // Propagate event.
715
0
        pListener->propertiesChange( pSeq.getEvents() );
716
717
0
        it = aListeners.begin();
718
0
    }
719
0
}
720
721
void ContentImplHelper::notifyPropertySetInfoChange(
722
    const beans::PropertySetInfoChangeEvent& evt ) const
723
0
{
724
0
    if ( !m_pImpl->m_pPropSetChangeListeners )
725
0
        return;
726
727
    // Notify event listeners.
728
0
    m_pImpl->m_pPropSetChangeListeners->notifyEach( &beans::XPropertySetInfoChangeListener::propertySetInfoChange, evt );
729
0
}
730
731
void ContentImplHelper::notifyContentEvent(
732
    const css::ucb::ContentEvent& evt ) const
733
0
{
734
0
    if ( !m_pImpl->m_pContentEventListeners )
735
0
        return;
736
737
    // Notify event listeners.
738
0
    m_pImpl->m_pContentEventListeners->notifyEach( &css::ucb::XContentEventListener::contentEvent, evt);
739
0
}
740
741
void ContentImplHelper::inserted()
742
0
{
743
    // Content is not yet registered at provider.
744
0
    m_xProvider->registerNewContent( this );
745
746
    // If the parent content is currently not instantiated, there can be
747
    // no listeners interested in changes ;-)
748
749
0
    rtl::Reference< ContentImplHelper > xParent
750
0
                = m_xProvider->queryExistingContent( getParentURL() );
751
752
0
    if ( xParent.is() )
753
0
    {
754
0
        css::ucb::ContentEvent aEvt(
755
0
            xParent->getXWeak(), // Source
756
0
            css::ucb::ContentAction::INSERTED,        // Action
757
0
            this,                                                // Content
758
0
            xParent->getIdentifier() );                          // Id
759
0
        xParent->notifyContentEvent( aEvt );
760
0
    }
761
0
}
762
763
void ContentImplHelper::deleted()
764
0
{
765
0
    uno::Reference< css::ucb::XContent > xThis = this;
766
767
0
    rtl::Reference< ContentImplHelper > xParent
768
0
                    = m_xProvider->queryExistingContent( getParentURL() );
769
770
0
    if ( xParent.is() )
771
0
    {
772
        // Let parent notify "REMOVED" event.
773
0
        css::ucb::ContentEvent aEvt(
774
0
            xParent->getXWeak(),
775
0
            css::ucb::ContentAction::REMOVED,
776
0
            this,
777
0
            xParent->getIdentifier()    );
778
0
        xParent->notifyContentEvent( aEvt );
779
0
    }
780
781
    // Notify "DELETED" event.
782
0
    css::ucb::ContentEvent aEvt1(
783
0
        getXWeak(),
784
0
        css::ucb::ContentAction::DELETED,
785
0
        this,
786
0
        getIdentifier() );
787
0
    notifyContentEvent( aEvt1 );
788
789
0
    m_xProvider->removeContent( this );
790
0
}
791
792
bool ContentImplHelper::exchange(
793
    const uno::Reference< css::ucb::XContentIdentifier >& rNewId )
794
0
{
795
0
    uno::Reference< css::ucb::XContent > xThis = this;
796
797
0
    osl::ClearableMutexGuard aGuard( m_aMutex );
798
799
0
    rtl::Reference< ContentImplHelper > xContent
800
0
        = m_xProvider->queryExistingContent( rNewId );
801
0
    if ( xContent.is() )
802
0
    {
803
        // @@@
804
        // Big trouble. Another object with the new identity exists.
805
        // How shall I mutate to / merge with the other object?
806
0
        return false;
807
0
    }
808
809
0
    uno::Reference< css::ucb::XContentIdentifier > xOldId
810
0
        = getIdentifier();
811
812
    // Re-insert at provider.
813
0
    m_xProvider->removeContent( this );
814
0
    m_xIdentifier = rNewId;
815
0
    m_xProvider->registerNewContent( this );
816
817
0
    aGuard.clear();
818
819
    // Notify "EXCHANGED" event.
820
0
    css::ucb::ContentEvent aEvt(
821
0
        getXWeak(),
822
0
        css::ucb::ContentAction::EXCHANGED,
823
0
        this,
824
0
        xOldId );
825
0
    notifyContentEvent( aEvt );
826
0
    return true;
827
0
}
828
829
uno::Reference< css::ucb::XCommandInfo >
830
ContentImplHelper::getCommandInfo(
831
    const uno::Reference< css::ucb::XCommandEnvironment > & xEnv,
832
    bool bCache )
833
0
{
834
0
    osl::MutexGuard aGuard( m_aMutex );
835
836
0
    if ( !m_pImpl->m_xCommandsInfo.is() )
837
0
        m_pImpl->m_xCommandsInfo
838
0
            = new CommandProcessorInfo( xEnv, this );
839
0
    else if ( !bCache )
840
0
        m_pImpl->m_xCommandsInfo->reset();
841
842
0
    return m_pImpl->m_xCommandsInfo;
843
0
}
844
845
uno::Reference< beans::XPropertySetInfo >
846
ContentImplHelper::getPropertySetInfo(
847
    const uno::Reference< css::ucb::XCommandEnvironment > & xEnv,
848
    bool bCache )
849
0
{
850
0
    osl::MutexGuard aGuard( m_aMutex );
851
852
0
    if ( !m_pImpl->m_xPropSetInfo.is() )
853
0
        m_pImpl->m_xPropSetInfo
854
0
            = new PropertySetInfo( xEnv, this );
855
0
    else if ( !bCache )
856
0
        m_pImpl->m_xPropSetInfo->reset();
857
858
0
    return m_pImpl->m_xPropSetInfo;
859
0
}
860
861
} // namespace ucbhelper
862
863
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */