1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_hier.hxx"
26 
27 /**************************************************************************
28 								TODO
29  **************************************************************************
30 
31  Note: Configuration Management classes do not support XAggregation.
32        So I have to wrap the interesting interfaces manually.
33 
34  *************************************************************************/
35 #include "hierarchydatasource.hxx"
36 #include <osl/diagnose.h>
37 
38 #include "osl/doublecheckedlocking.h"
39 #include <cppuhelper/interfacecontainer.hxx>
40 #include <com/sun/star/beans/PropertyValue.hpp>
41 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
42 #include <com/sun/star/container/XNameContainer.hpp>
43 #include <com/sun/star/util/XChangesBatch.hpp>
44 #include <com/sun/star/util/XChangesNotifier.hpp>
45 
46 using namespace com::sun::star;
47 using namespace hierarchy_ucp;
48 
49 //=========================================================================
50 
51 // describe path of cfg entry
52 #define	CFGPROPERTY_NODEPATH	"nodepath"
53 // true->async. update; false->sync. update
54 #define	CFGPROPERTY_LAZYWRITE	"lazywrite"
55 
56 #define READ_SERVICE_NAME      "com.sun.star.ucb.HierarchyDataReadAccess"
57 #define READWRITE_SERVICE_NAME "com.sun.star.ucb.HierarchyDataReadWriteAccess"
58 
59 #define CONFIG_PROVIDER_SERVICE_NAME  \
60                         "com.sun.star.configuration.ConfigurationProvider"
61 #define CONFIG_READ_SERVICE_NAME      \
62                         "com.sun.star.configuration.ConfigurationAccess"
63 #define CONFIG_READWRITE_SERVICE_NAME \
64                         "com.sun.star.configuration.ConfigurationUpdateAccess"
65 #define CONFIG_DATA_ROOT_KEY          \
66                         "/org.openoffice.ucb.Hierarchy/Root"
67 
68 //=========================================================================
69 
70 namespace hcp_impl
71 {
72 
73 //=========================================================================
74 //
75 // HierarchyDataReadAccess Implementation.
76 //
77 //=========================================================================
78 
79 class HierarchyDataAccess : public cppu::OWeakObject,
80                             public lang::XServiceInfo,
81                             public lang::XTypeProvider,
82                             public lang::XComponent,
83                             public lang::XSingleServiceFactory,
84                             public container::XHierarchicalNameAccess,
85                             public container::XNameContainer,
86                             public util::XChangesNotifier,
87                             public util::XChangesBatch
88 {
89     osl::Mutex m_aMutex;
90     uno::Reference< uno::XInterface > m_xConfigAccess;
91     uno::Reference< lang::XComponent >                   m_xCfgC;
92     uno::Reference< lang::XSingleServiceFactory >        m_xCfgSSF;
93     uno::Reference< container::XHierarchicalNameAccess > m_xCfgHNA;
94     uno::Reference< container::XNameContainer >          m_xCfgNC;
95     uno::Reference< container::XNameReplace >            m_xCfgNR;
96     uno::Reference< container::XNameAccess >             m_xCfgNA;
97     uno::Reference< container::XElementAccess >          m_xCfgEA;
98     uno::Reference< util::XChangesNotifier >             m_xCfgCN;
99     uno::Reference< util::XChangesBatch >                m_xCfgCB;
100     bool m_bReadOnly;
101 
102 public:
103     HierarchyDataAccess( const uno::Reference<
104                                         uno::XInterface > & xConfigAccess,
105                          bool bReadOnly );
106     virtual ~HierarchyDataAccess();
107 
108 	// XInterface
109 	XINTERFACE_DECL()
110 
111     // XServiceInfo
112 	XSERVICEINFO_DECL()
113 
114 	// XTypeProvider
115 	XTYPEPROVIDER_DECL()
116 
117     // XComponent
118     virtual void SAL_CALL
119     dispose()
120         throw ( uno::RuntimeException );
121     virtual void SAL_CALL
122     addEventListener( const uno::Reference< lang::XEventListener > & xListener )
123         throw ( uno::RuntimeException );
124     virtual void SAL_CALL
125     removeEventListener( const uno::Reference<
126                             lang::XEventListener > & aListener )
127         throw ( uno::RuntimeException );
128 
129     // XSingleServiceFactory
130     virtual uno::Reference< uno::XInterface > SAL_CALL
131     createInstance()
132         throw ( uno::Exception, uno::RuntimeException );
133     virtual uno::Reference< uno::XInterface > SAL_CALL
134     createInstanceWithArguments( const uno::Sequence< uno::Any > & aArguments )
135         throw ( uno::Exception, uno::RuntimeException );
136 
137     // XHierarchicalNameAccess
138     virtual uno::Any SAL_CALL
139     getByHierarchicalName( const rtl::OUString & aName )
140         throw ( container::NoSuchElementException, uno::RuntimeException );
141     virtual sal_Bool SAL_CALL
142     hasByHierarchicalName( const rtl::OUString & aName )
143         throw ( uno::RuntimeException );
144 
145     // XNameContainer
146     virtual void SAL_CALL
147     insertByName( const rtl::OUString & aName, const uno::Any & aElement )
148         throw ( lang::IllegalArgumentException,
149                 container::ElementExistException,
150                 lang::WrappedTargetException,
151                 uno::RuntimeException );
152     virtual void SAL_CALL
153     removeByName( const rtl::OUString & Name )
154         throw ( container::NoSuchElementException,
155                 lang::WrappedTargetException,
156                 uno::RuntimeException );
157 
158     // XNameReplace ( base of XNameContainer )
159     virtual void SAL_CALL
160     replaceByName( const rtl::OUString & aName, const uno::Any & aElement )
161         throw ( lang::IllegalArgumentException,
162                 container::NoSuchElementException,
163                 lang::WrappedTargetException,
164                 uno::RuntimeException );
165 
166     // XNameAccess ( base of XNameReplace )
167     virtual uno::Any SAL_CALL
168     getByName( const rtl::OUString & aName )
169         throw ( container::NoSuchElementException,
170                 lang::WrappedTargetException,
171                 uno::RuntimeException );
172     virtual uno::Sequence< rtl::OUString > SAL_CALL
173     getElementNames()
174         throw ( uno::RuntimeException );
175     virtual sal_Bool SAL_CALL
176     hasByName( const rtl::OUString & aName )
177         throw ( uno::RuntimeException );
178 
179     // XElementAccess ( base of XNameAccess )
180     virtual uno::Type SAL_CALL
181     getElementType()
182         throw ( uno::RuntimeException );
183     virtual sal_Bool SAL_CALL
184     hasElements()
185         throw ( uno::RuntimeException );
186 
187     // XChangesNotifier
188     virtual void SAL_CALL
189     addChangesListener( const uno::Reference<
190                             util::XChangesListener > & aListener )
191         throw ( uno::RuntimeException );
192     virtual void SAL_CALL
193     removeChangesListener( const uno::Reference<
194                             util::XChangesListener > & aListener )
195         throw ( uno::RuntimeException );
196 
197     // XChangesBatch
198     virtual void SAL_CALL
199     commitChanges()
200         throw ( lang::WrappedTargetException, uno::RuntimeException );
201     virtual sal_Bool SAL_CALL
202     hasPendingChanges()
203         throw ( uno::RuntimeException );
204     virtual uno::Sequence< util::ElementChange > SAL_CALL
205     getPendingChanges()
206         throw ( uno::RuntimeException );
207 };
208 
209 } // namespace hcp_impl
210 
211 using namespace hcp_impl;
212 
213 //=========================================================================
214 //=========================================================================
215 //
216 // HierarchyDataSource Implementation.
217 //
218 //=========================================================================
219 //=========================================================================
220 
HierarchyDataSource(const uno::Reference<lang::XMultiServiceFactory> & rxServiceMgr)221 HierarchyDataSource::HierarchyDataSource(
222         const uno::Reference< lang::XMultiServiceFactory > & rxServiceMgr )
223 : m_xSMgr( rxServiceMgr ),
224   m_pDisposeEventListeners( 0 )
225 {
226 }
227 
228 //=========================================================================
229 // virtual
~HierarchyDataSource()230 HierarchyDataSource::~HierarchyDataSource()
231 {
232     delete m_pDisposeEventListeners;
233 }
234 
235 //=========================================================================
236 //
237 // XInterface methods.
238 //
239 //=========================================================================
240 
241 XINTERFACE_IMPL_4( HierarchyDataSource,
242                    lang::XTypeProvider,
243                    lang::XServiceInfo,
244                    lang::XComponent,
245                    lang::XMultiServiceFactory );
246 
247 //=========================================================================
248 //
249 // XTypeProvider methods.
250 //
251 //=========================================================================
252 
253 XTYPEPROVIDER_IMPL_4( HierarchyDataSource,
254                       lang::XTypeProvider,
255                       lang::XServiceInfo,
256                       lang::XComponent,
257                       lang::XMultiServiceFactory );
258 
259 //=========================================================================
260 //
261 // XServiceInfo methods.
262 //
263 //=========================================================================
264 
265 XSERVICEINFO_IMPL_0( HierarchyDataSource,
266                      rtl::OUString::createFromAscii(
267                         "com.sun.star.comp.ucb.HierarchyDataSource" ) )
268 {
269     uno::Sequence< rtl::OUString > aSNS( 2 );
270     aSNS[ 0 ] = rtl::OUString::createFromAscii(
271                     "com.sun.star.ucb.DefaultHierarchyDataSource" );
272     aSNS[ 1 ] = rtl::OUString::createFromAscii(
273                     "com.sun.star.ucb.HierarchyDataSource" );
274     return aSNS;
275 }
276 
277 ONE_INSTANCE_SERVICE_FACTORY_IMPL( HierarchyDataSource );
278 
279 //=========================================================================
280 //
281 // XComponent methods.
282 //
283 //=========================================================================
284 
285 // virtual
dispose()286 void SAL_CALL HierarchyDataSource::dispose()
287     throw( uno::RuntimeException )
288 {
289 	osl::Guard< osl::Mutex > aGuard( m_aMutex );
290 
291     if ( m_pDisposeEventListeners && m_pDisposeEventListeners->getLength() )
292 	{
293         lang::EventObject aEvt;
294         aEvt.Source = static_cast< lang::XComponent * >( this );
295         m_pDisposeEventListeners->disposeAndClear( aEvt );
296 	}
297 }
298 
299 //=========================================================================
300 // virtual
addEventListener(const uno::Reference<lang::XEventListener> & Listener)301 void SAL_CALL HierarchyDataSource::addEventListener(
302                     const uno::Reference< lang::XEventListener > & Listener )
303     throw( uno::RuntimeException )
304 {
305 	osl::Guard< osl::Mutex > aGuard( m_aMutex );
306 
307     if ( !m_pDisposeEventListeners )
308         m_pDisposeEventListeners
309             = new cppu::OInterfaceContainerHelper( m_aMutex );
310 
311     m_pDisposeEventListeners->addInterface( Listener );
312 }
313 
314 //=========================================================================
315 // virtual
removeEventListener(const uno::Reference<lang::XEventListener> & Listener)316 void SAL_CALL HierarchyDataSource::removeEventListener(
317                     const uno::Reference< lang::XEventListener > & Listener )
318     throw( uno::RuntimeException )
319 {
320 	osl::Guard< osl::Mutex > aGuard( m_aMutex );
321 
322     if ( m_pDisposeEventListeners )
323         m_pDisposeEventListeners->removeInterface( Listener );
324 }
325 
326 //=========================================================================
327 //
328 // XMultiServiceFactory methods.
329 //
330 //=========================================================================
331 
332 // virtual
333 uno::Reference< uno::XInterface > SAL_CALL
createInstance(const rtl::OUString & aServiceSpecifier)334 HierarchyDataSource::createInstance( const rtl::OUString & aServiceSpecifier )
335     throw ( uno::Exception, uno::RuntimeException )
336 {
337     // Create view to root node.
338 
339     beans::PropertyValue aProp;
340     aProp.Name = rtl::OUString(
341                         RTL_CONSTASCII_USTRINGPARAM( CFGPROPERTY_NODEPATH ) );
342     aProp.Value <<=
343         rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( CONFIG_DATA_ROOT_KEY ) );
344 
345     uno::Sequence< uno::Any > aArguments( 1 );
346     aArguments[ 0 ] <<= aProp;
347 
348     return createInstanceWithArguments( aServiceSpecifier, aArguments, false );
349 }
350 
351 //=========================================================================
352 // virtual
353 uno::Reference< uno::XInterface > SAL_CALL
createInstanceWithArguments(const rtl::OUString & ServiceSpecifier,const uno::Sequence<uno::Any> & Arguments)354 HierarchyDataSource::createInstanceWithArguments(
355                                 const rtl::OUString & ServiceSpecifier,
356                                 const uno::Sequence< uno::Any > & Arguments )
357     throw ( uno::Exception, uno::RuntimeException )
358 {
359     return createInstanceWithArguments( ServiceSpecifier, Arguments, true );
360 }
361 
362 //=========================================================================
363 // virtual
364 uno::Sequence< rtl::OUString > SAL_CALL
getAvailableServiceNames()365 HierarchyDataSource::getAvailableServiceNames()
366     throw ( uno::RuntimeException )
367 {
368     uno::Sequence< rtl::OUString > aNames( 2 );
369     aNames[ 0 ] = rtl::OUString(
370                     RTL_CONSTASCII_USTRINGPARAM( READ_SERVICE_NAME ) );
371     aNames[ 1 ] = rtl::OUString(
372                     RTL_CONSTASCII_USTRINGPARAM( READWRITE_SERVICE_NAME ) );
373     return aNames;
374 }
375 
376 //=========================================================================
377 //
378 // Non-interface methods
379 //
380 //=========================================================================
381 
382 uno::Reference< uno::XInterface > SAL_CALL
createInstanceWithArguments(const rtl::OUString & ServiceSpecifier,const uno::Sequence<uno::Any> & Arguments,bool bCheckArgs)383 HierarchyDataSource::createInstanceWithArguments(
384                                 const rtl::OUString & ServiceSpecifier,
385                                 const uno::Sequence< uno::Any > & Arguments,
386                                 bool bCheckArgs )
387     throw ( uno::Exception, uno::RuntimeException )
388 {
389     osl::Guard< osl::Mutex > aGuard( m_aMutex );
390 
391     // Check service specifier.
392     bool bReadOnly  = !!ServiceSpecifier.equalsAsciiL(
393                         RTL_CONSTASCII_STRINGPARAM( READ_SERVICE_NAME ) );
394     bool bReadWrite = !bReadOnly &&
395                       ServiceSpecifier.equalsAsciiL(
396                         RTL_CONSTASCII_STRINGPARAM( READWRITE_SERVICE_NAME ) );
397 
398     if ( !bReadOnly && !bReadWrite )
399     {
400         OSL_ENSURE( false,
401                     "HierarchyDataSource::createInstanceWithArguments - "
402                     "Unsupported service specifier!" );
403         return uno::Reference< uno::XInterface >();
404     }
405 
406     uno::Sequence< uno::Any > aNewArgs( Arguments );
407 
408     bool bHasLazyWriteProp = bReadOnly; // property must be added only if
409                                         // a writable view is requested.
410     if ( bCheckArgs )
411     {
412         // Check arguments.
413         bool bHasNodePath = false;
414         sal_Int32 nCount = Arguments.getLength();
415         for ( sal_Int32 n = 0; n < nCount; ++n )
416         {
417             beans::PropertyValue aProp;
418             if ( Arguments[ n ] >>= aProp )
419             {
420                 if ( aProp.Name.equalsAsciiL(
421                         RTL_CONSTASCII_STRINGPARAM( CFGPROPERTY_NODEPATH ) ) )
422                 {
423                     rtl::OUString aPath;
424                     if ( aProp.Value >>= aPath )
425                     {
426                         bHasNodePath = true;
427 
428                         // Create path to data inside the configuration.
429                         rtl::OUString aConfigPath;
430                         if ( !createConfigPath( aPath, aConfigPath ) )
431                         {
432                             OSL_ENSURE( false,
433                                 "HierarchyDataSource::"
434                                 "createInstanceWithArguments - "
435                                 "Invalid node path!" );
436                             return uno::Reference< uno::XInterface >();
437                         }
438 
439                         aProp.Value <<= aConfigPath;
440 
441                         // Set new path in arguments.
442                         aNewArgs[ n ] <<= aProp;
443 
444                         if ( bHasLazyWriteProp )
445                             break;
446                     }
447                     else
448                     {
449                         OSL_ENSURE( false,
450                             "HierarchyDataSource::createInstanceWithArguments - "
451                             "Invalid type for property 'nodepath'!" );
452                         return uno::Reference< uno::XInterface >();
453                     }
454                 }
455                 else if ( aProp.Name.equalsAsciiL(
456                             RTL_CONSTASCII_STRINGPARAM(
457                                 CFGPROPERTY_LAZYWRITE ) ) )
458                 {
459                     if ( aProp.Value.getValueType() == getCppuBooleanType() )
460                     {
461                         bHasLazyWriteProp = true;
462 
463                         if ( bHasNodePath )
464                             break;
465                     }
466                     else
467                     {
468                         OSL_ENSURE( false,
469                             "HierarchyDataSource::createInstanceWithArguments - "
470                             "Invalid type for property 'lazywrite'!" );
471                         return uno::Reference< uno::XInterface >();
472                     }
473                 }
474             }
475         }
476 
477         if ( !bHasNodePath )
478         {
479             OSL_ENSURE( false,
480                         "HierarchyDataSource::createInstanceWithArguments - "
481                         "No 'nodepath' property!" );
482             return uno::Reference< uno::XInterface >();
483         }
484     }
485 
486     // Create Configuration Provider.
487     uno::Reference< lang::XMultiServiceFactory > xProv = getConfigProvider();
488     if ( !xProv.is() )
489         return uno::Reference< uno::XInterface >();
490 
491     uno::Reference< uno::XInterface > xConfigAccess;
492     try
493     {
494         if ( bReadOnly )
495         {
496             // Create configuration read-only access object.
497             xConfigAccess = xProv->createInstanceWithArguments(
498                                 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
499                                         CONFIG_READ_SERVICE_NAME ) ),
500                                 aNewArgs );
501         }
502         else
503         {
504             // Append 'lazywrite' property value, if not already present.
505             if ( !bHasLazyWriteProp )
506             {
507                 sal_Int32 nLen = aNewArgs.getLength();
508                 aNewArgs.realloc( nLen + 1 );
509 
510                 beans::PropertyValue aProp;
511                 aProp.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
512                                                     CFGPROPERTY_LAZYWRITE ) );
513                 aProp.Value <<= sal_True;
514                 aNewArgs[ nLen ] <<= aProp;
515             }
516 
517             // Create configuration read-write access object.
518             xConfigAccess = xProv->createInstanceWithArguments(
519                                 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
520                                         CONFIG_READWRITE_SERVICE_NAME ) ),
521                                 aNewArgs );
522         }
523     }
524     catch ( uno::Exception const & )
525     {
526         OSL_ENSURE( false,
527                     "HierarchyDataSource::createInstanceWithArguments - "
528                     "Cannot instanciate configuration access!" );
529         throw;
530     }
531 
532     if ( !xConfigAccess.is() )
533     {
534         OSL_ENSURE( false,
535                     "HierarchyDataSource::createInstanceWithArguments - "
536                     "Cannot instanciate configuration access!" );
537         return xConfigAccess;
538     }
539 
540     return uno::Reference< uno::XInterface >(
541                 static_cast< cppu::OWeakObject * >(
542                     new HierarchyDataAccess( xConfigAccess, bReadOnly ) ) );
543 }
544 
545 //=========================================================================
546 uno::Reference< lang::XMultiServiceFactory >
getConfigProvider()547 HierarchyDataSource::getConfigProvider()
548 {
549 	if ( !m_xConfigProvider.is() )
550 	{
551         osl::Guard< osl::Mutex > aGuard( m_aMutex );
552 		if ( !m_xConfigProvider.is() )
553 		{
554 			try
555 			{
556                 m_xConfigProvider
557                     = uno::Reference< lang::XMultiServiceFactory >(
558                         m_xSMgr->createInstance(
559                             rtl::OUString(
560                                 RTL_CONSTASCII_USTRINGPARAM(
561                                     CONFIG_PROVIDER_SERVICE_NAME ) ) ),
562                         uno::UNO_QUERY );
563 
564                 OSL_ENSURE( m_xConfigProvider.is(),
565                             "HierarchyDataSource::getConfigProvider - "
566                             "No configuration provider!" );
567 			}
568             catch ( uno::Exception const & )
569 			{
570                 OSL_ENSURE( false,
571                             "HierarchyDataSource::getConfigProvider - "
572 				   			"caught exception!" );
573 			}
574 		}
575 	}
576 
577 	return m_xConfigProvider;
578 }
579 
580 //=========================================================================
createConfigPath(const rtl::OUString & rInPath,rtl::OUString & rOutPath)581 bool HierarchyDataSource::createConfigPath(
582                 const rtl::OUString & rInPath, rtl::OUString & rOutPath )
583 {
584     if ( rInPath.getLength() )
585     {
586         if ( rInPath.indexOf( '/' ) == 0 )
587         {
588             OSL_ENSURE( false,
589                         "HierarchyDataSource::createConfigPath - "
590                         "Leading slash in node path!" );
591             return false;
592         }
593 
594         if ( rInPath.lastIndexOf( '/' ) == rInPath.getLength() - 1 )
595         {
596             OSL_ENSURE( false,
597                         "HierarchyDataSource::createConfigPath - "
598                         "Trailing slash in node path!" );
599             return false;
600         }
601 
602         rtl::OUString aOutPath(
603                 RTL_CONSTASCII_USTRINGPARAM( CONFIG_DATA_ROOT_KEY "/" ) );
604         aOutPath += rInPath;
605         rOutPath = aOutPath;
606     }
607     else
608     {
609         rOutPath = rtl::OUString(
610                     RTL_CONSTASCII_USTRINGPARAM( CONFIG_DATA_ROOT_KEY ) );
611     }
612 
613     return true;
614 }
615 
616 //=========================================================================
617 //=========================================================================
618 //
619 // HierarchyDataAccess Implementation.
620 //
621 //=========================================================================
622 //=========================================================================
623 
624 #define ENSURE_ORIG_INTERFACE( interface_name, member_name )    \
625     m_xCfg##member_name;                                        \
626     if ( !m_xCfg##member_name.is() )                            \
627     {                                                           \
628         osl::Guard< osl::Mutex > aGuard( m_aMutex );            \
629         if ( !m_xCfg##member_name.is() )                        \
630             m_xCfg##member_name                                 \
631                 = uno::Reference< interface_name >(             \
632                     m_xConfigAccess, uno::UNO_QUERY );          \
633         xOrig = m_xCfg##member_name;                            \
634     }
635 
636 //=========================================================================
HierarchyDataAccess(const uno::Reference<uno::XInterface> & xConfigAccess,bool bReadOnly)637 HierarchyDataAccess::HierarchyDataAccess( const uno::Reference<
638                                             uno::XInterface > & xConfigAccess,
639                                           bool bReadOnly )
640 : m_xConfigAccess( xConfigAccess ),
641   m_bReadOnly( bReadOnly )
642 {
643 }
644 
645 //=========================================================================
646 // virtual
~HierarchyDataAccess()647 HierarchyDataAccess::~HierarchyDataAccess()
648 {
649 }
650 
651 //=========================================================================
652 //
653 // XInterface methods.
654 //
655 //=========================================================================
656 
657 XINTERFACE_COMMON_IMPL( HierarchyDataAccess );
658 
659 //=========================================================================
660 // virtual
queryInterface(const uno::Type & aType)661 uno::Any SAL_CALL HierarchyDataAccess::queryInterface( const uno::Type & aType )
662     throw ( uno::RuntimeException )
663 {
664     // Interfaces supported in read-only and read-write mode.
665     uno::Any aRet = cppu::queryInterface( aType,
666                 static_cast< lang::XTypeProvider * >( this ),
667                 static_cast< lang::XServiceInfo * >( this ),
668                 static_cast< lang::XComponent * >( this ),
669                 static_cast< container::XHierarchicalNameAccess * >( this ),
670                 static_cast< container::XNameAccess * >( this ),
671                 static_cast< container::XElementAccess * >( this ),
672                 static_cast< util::XChangesNotifier * >( this ) );
673 
674     // Interfaces supported only in read-write mode.
675     if ( !aRet.hasValue() && !m_bReadOnly )
676     {
677         aRet = cppu::queryInterface( aType,
678                 static_cast< lang::XSingleServiceFactory * >( this ),
679                 static_cast< container::XNameContainer * >( this ),
680                 static_cast< container::XNameReplace * >( this ),
681                 static_cast< util::XChangesBatch * >( this ) );
682     }
683 
684     return aRet.hasValue() ? aRet : OWeakObject::queryInterface( aType );
685 }
686 
687 //=========================================================================
688 //
689 // XTypeProvider methods.
690 //
691 //=========================================================================
692 
693 XTYPEPROVIDER_COMMON_IMPL( HierarchyDataAccess );
694 
695 //=========================================================================
696 // virtual
getTypes()697 uno::Sequence< uno::Type > SAL_CALL HierarchyDataAccess::getTypes()
698     throw( uno::RuntimeException )
699 {
700     cppu::OTypeCollection * pCollection = 0;
701 
702     if ( m_bReadOnly )
703     {
704         static cppu::OTypeCollection* pReadOnlyTypes = 0;
705 
706         pCollection = pReadOnlyTypes;
707         if ( !pCollection )
708         {
709             osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
710 
711             pCollection = pReadOnlyTypes;
712             if ( !pCollection )
713             {
714                 static cppu::OTypeCollection aCollection(
715                     CPPU_TYPE_REF( lang::XTypeProvider ),
716                     CPPU_TYPE_REF( lang::XServiceInfo ),
717                     CPPU_TYPE_REF( lang::XComponent ),
718                     CPPU_TYPE_REF( container::XHierarchicalNameAccess ),
719                     CPPU_TYPE_REF( container::XNameAccess ),
720                     CPPU_TYPE_REF( util::XChangesNotifier ) );
721                 pCollection = &aCollection;
722                 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
723                 pReadOnlyTypes = pCollection;
724             }
725         }
726         else {
727             OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
728         }
729     }
730     else
731     {
732         static cppu::OTypeCollection* pReadWriteTypes = 0;
733 
734         pCollection = pReadWriteTypes;
735         if ( !pCollection )
736         {
737             osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
738 
739             pCollection = pReadWriteTypes;
740             if ( !pCollection )
741             {
742                 static cppu::OTypeCollection aCollection(
743                     CPPU_TYPE_REF( lang::XTypeProvider ),
744                     CPPU_TYPE_REF( lang::XServiceInfo ),
745                     CPPU_TYPE_REF( lang::XComponent ),
746                     CPPU_TYPE_REF( lang::XSingleServiceFactory ),
747                     CPPU_TYPE_REF( container::XHierarchicalNameAccess ),
748                     CPPU_TYPE_REF( container::XNameContainer ),
749                     CPPU_TYPE_REF( util::XChangesBatch ),
750                     CPPU_TYPE_REF( util::XChangesNotifier ) );
751                 pCollection = &aCollection;
752                 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
753                 pReadWriteTypes = pCollection;
754             }
755         }
756         else {
757             OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
758         }
759     }
760 
761     return (*pCollection).getTypes();
762 }
763 
764 //=========================================================================
765 //
766 // XServiceInfo methods.
767 //
768 //=========================================================================
769 
770 XSERVICEINFO_NOFACTORY_IMPL_0(
771         HierarchyDataAccess,
772         rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
773                             "com.sun.star.comp.ucb.HierarchyDataAccess" ) ) )
774 {
775     uno::Sequence< rtl::OUString > aSNS( 2 );
776     aSNS[ 0 ] = rtl::OUString(
777                         RTL_CONSTASCII_USTRINGPARAM( READ_SERVICE_NAME ) );
778     aSNS[ 1 ] = rtl::OUString(
779                         RTL_CONSTASCII_USTRINGPARAM( READWRITE_SERVICE_NAME ) );
780     return aSNS;
781 }
782 
783 //=========================================================================
784 //
785 // XComponent methods.
786 //
787 //=========================================================================
788 
789 // virtual
dispose()790 void SAL_CALL HierarchyDataAccess::dispose()
791     throw ( uno::RuntimeException )
792 {
793     uno::Reference< lang::XComponent > xOrig
794         = ENSURE_ORIG_INTERFACE( lang::XComponent, C );
795 
796     OSL_ENSURE( xOrig.is(),
797                 "HierarchyDataAccess : Data source is not an XComponent!" );
798     xOrig->dispose();
799 }
800 
801 //=========================================================================
802 // virtual
addEventListener(const uno::Reference<lang::XEventListener> & xListener)803 void SAL_CALL HierarchyDataAccess::addEventListener(
804                     const uno::Reference< lang::XEventListener > & xListener )
805     throw ( uno::RuntimeException )
806 {
807     uno::Reference< lang::XComponent > xOrig
808         = ENSURE_ORIG_INTERFACE( lang::XComponent, C );
809 
810     OSL_ENSURE( xOrig.is(),
811                 "HierarchyDataAccess : Data source is not an XComponent!" );
812     xOrig->addEventListener( xListener );
813 }
814 
815 //=========================================================================
816 // virtual
removeEventListener(const uno::Reference<lang::XEventListener> & aListener)817 void SAL_CALL HierarchyDataAccess::removeEventListener(
818                     const uno::Reference< lang::XEventListener > & aListener )
819     throw ( uno::RuntimeException )
820 {
821     uno::Reference< lang::XComponent > xOrig
822         = ENSURE_ORIG_INTERFACE( lang::XComponent, C );
823 
824     OSL_ENSURE( xOrig.is(),
825                 "HierarchyDataAccess : Data source is not an XComponent!" );
826     xOrig->removeEventListener( aListener );
827 }
828 
829 //=========================================================================
830 //
831 // XHierarchicalNameAccess methods.
832 //
833 //=========================================================================
834 
835 // virtual
getByHierarchicalName(const rtl::OUString & aName)836 uno::Any SAL_CALL HierarchyDataAccess::getByHierarchicalName(
837                                                 const rtl::OUString & aName )
838     throw ( container::NoSuchElementException, uno::RuntimeException )
839 {
840     uno::Reference< container::XHierarchicalNameAccess > xOrig
841         = ENSURE_ORIG_INTERFACE( container::XHierarchicalNameAccess, HNA );
842 
843     OSL_ENSURE( xOrig.is(),
844                 "HierarchyDataAccess : "
845                 "Data source is not an XHierarchicalNameAccess!" );
846     return xOrig->getByHierarchicalName( aName );
847 }
848 
849 //=========================================================================
850 // virtual
hasByHierarchicalName(const rtl::OUString & aName)851 sal_Bool SAL_CALL HierarchyDataAccess::hasByHierarchicalName(
852                                                 const rtl::OUString & aName )
853     throw ( uno::RuntimeException )
854 {
855     uno::Reference< container::XHierarchicalNameAccess > xOrig
856         = ENSURE_ORIG_INTERFACE( container::XHierarchicalNameAccess, HNA );
857 
858     OSL_ENSURE( xOrig.is(),
859                 "HierarchyDataAccess : "
860                 "Data source is not an XHierarchicalNameAccess!" );
861     return xOrig->hasByHierarchicalName( aName );
862 }
863 
864 //=========================================================================
865 //
866 // XNameAccess methods.
867 //
868 //=========================================================================
869 
870 // virtual
getByName(const rtl::OUString & aName)871 uno::Any SAL_CALL HierarchyDataAccess::getByName( const rtl::OUString & aName )
872     throw ( container::NoSuchElementException,
873             lang::WrappedTargetException,
874             uno::RuntimeException )
875 {
876     uno::Reference< container::XNameAccess > xOrig
877         = ENSURE_ORIG_INTERFACE( container::XNameAccess, NA );
878 
879     OSL_ENSURE( xOrig.is(),
880                 "HierarchyDataAccess : Data source is not an XNameAccess!" );
881     return xOrig->getByName( aName );
882 }
883 
884 //=========================================================================
885 // virtual
getElementNames()886 uno::Sequence< rtl::OUString > SAL_CALL HierarchyDataAccess::getElementNames()
887     throw ( uno::RuntimeException )
888 {
889     uno::Reference< container::XNameAccess > xOrig
890         = ENSURE_ORIG_INTERFACE( container::XNameAccess, NA );
891 
892     OSL_ENSURE( xOrig.is(),
893                 "HierarchyDataAccess : Data source is not an XNameAccess!" );
894     return xOrig->getElementNames();
895 }
896 
897 //=========================================================================
898 // virtual
hasByName(const rtl::OUString & aName)899 sal_Bool SAL_CALL HierarchyDataAccess::hasByName( const rtl::OUString & aName )
900     throw ( uno::RuntimeException )
901 {
902     uno::Reference< container::XNameAccess > xOrig
903         = ENSURE_ORIG_INTERFACE( container::XNameAccess, NA );
904 
905     OSL_ENSURE( xOrig.is(),
906                 "HierarchyDataAccess : Data source is not an XNameAccess!" );
907     return xOrig->hasByName( aName );
908 }
909 
910 //=========================================================================
911 //
912 // XElementAccess methods.
913 //
914 //=========================================================================
915 
916 // virtual
getElementType()917 uno::Type SAL_CALL HierarchyDataAccess::getElementType()
918     throw ( uno::RuntimeException )
919 {
920     uno::Reference< container::XElementAccess > xOrig
921         = ENSURE_ORIG_INTERFACE( container::XElementAccess, EA );
922 
923     OSL_ENSURE( xOrig.is(),
924                 "HierarchyDataAccess : Data source is not an XElementAccess!" );
925     return xOrig->getElementType();
926 }
927 
928 //=========================================================================
929 // virtual
hasElements()930 sal_Bool SAL_CALL HierarchyDataAccess::hasElements()
931     throw ( uno::RuntimeException )
932 {
933     uno::Reference< container::XElementAccess > xOrig
934         = ENSURE_ORIG_INTERFACE( container::XElementAccess, EA );
935 
936     OSL_ENSURE( xOrig.is(),
937                 "HierarchyDataAccess : Data source is not an XElementAccess!" );
938     return xOrig->hasElements();
939 }
940 
941 //=========================================================================
942 //
943 // XChangesNotifier methods.
944 //
945 //=========================================================================
946 
947 // virtual
addChangesListener(const uno::Reference<util::XChangesListener> & aListener)948 void SAL_CALL HierarchyDataAccess::addChangesListener(
949                 const uno::Reference< util::XChangesListener > & aListener )
950     throw ( uno::RuntimeException )
951 {
952     uno::Reference< util::XChangesNotifier > xOrig
953         = ENSURE_ORIG_INTERFACE( util::XChangesNotifier, CN );
954 
955     OSL_ENSURE( xOrig.is(),
956             "HierarchyDataAccess : Data source is not an XChangesNotifier!" );
957     xOrig->addChangesListener( aListener );
958 }
959 
960 //=========================================================================
961 // virtual
removeChangesListener(const uno::Reference<util::XChangesListener> & aListener)962 void SAL_CALL HierarchyDataAccess::removeChangesListener(
963                 const uno::Reference< util::XChangesListener > & aListener )
964     throw ( uno::RuntimeException )
965 {
966     uno::Reference< util::XChangesNotifier > xOrig
967         = ENSURE_ORIG_INTERFACE( util::XChangesNotifier, CN );
968 
969     OSL_ENSURE( xOrig.is(),
970             "HierarchyDataAccess : Data source is not an XChangesNotifier!" );
971     xOrig->removeChangesListener( aListener );
972 }
973 
974 //=========================================================================
975 //
976 // XSingleServiceFactory methods.
977 //
978 //=========================================================================
979 
980 // virtual
createInstance()981 uno::Reference< uno::XInterface > SAL_CALL HierarchyDataAccess::createInstance()
982     throw ( uno::Exception, uno::RuntimeException )
983 {
984     uno::Reference< lang::XSingleServiceFactory > xOrig
985         = ENSURE_ORIG_INTERFACE( lang::XSingleServiceFactory, SSF );
986 
987     OSL_ENSURE( xOrig.is(),
988         "HierarchyDataAccess : Data source is not an XSingleServiceFactory!" );
989     return xOrig->createInstance();
990 }
991 
992 //=========================================================================
993 // virtual
994 uno::Reference< uno::XInterface > SAL_CALL
createInstanceWithArguments(const uno::Sequence<uno::Any> & aArguments)995 HierarchyDataAccess::createInstanceWithArguments(
996                             const uno::Sequence< uno::Any > & aArguments )
997     throw ( uno::Exception, uno::RuntimeException )
998 {
999     uno::Reference< lang::XSingleServiceFactory > xOrig
1000         = ENSURE_ORIG_INTERFACE( lang::XSingleServiceFactory, SSF );
1001 
1002     OSL_ENSURE( xOrig.is(),
1003         "HierarchyDataAccess : Data source is not an XSingleServiceFactory!" );
1004     return xOrig->createInstanceWithArguments( aArguments );
1005 }
1006 
1007 //=========================================================================
1008 //
1009 // XNameContainer methods.
1010 //
1011 //=========================================================================
1012 
1013 // virtual
1014 void SAL_CALL
insertByName(const rtl::OUString & aName,const uno::Any & aElement)1015 HierarchyDataAccess::insertByName( const rtl::OUString & aName,
1016                                    const uno::Any & aElement )
1017     throw ( lang::IllegalArgumentException,
1018             container::ElementExistException,
1019             lang::WrappedTargetException,
1020             uno::RuntimeException )
1021 {
1022     uno::Reference< container::XNameContainer > xOrig
1023         = ENSURE_ORIG_INTERFACE( container::XNameContainer, NC );
1024 
1025     OSL_ENSURE( xOrig.is(),
1026         "HierarchyDataAccess : Data source is not an XNameContainer!" );
1027     xOrig->insertByName( aName, aElement );
1028 }
1029 
1030 //=========================================================================
1031 // virtual
1032 void SAL_CALL
removeByName(const rtl::OUString & Name)1033 HierarchyDataAccess::removeByName( const rtl::OUString & Name )
1034     throw ( container::NoSuchElementException,
1035             lang::WrappedTargetException,
1036             uno::RuntimeException )
1037 {
1038     uno::Reference< container::XNameContainer > xOrig
1039         = ENSURE_ORIG_INTERFACE( container::XNameContainer, NC );
1040 
1041     OSL_ENSURE( xOrig.is(),
1042         "HierarchyDataAccess : Data source is not an XNameContainer!" );
1043     xOrig->removeByName( Name );
1044 }
1045 
1046 //=========================================================================
1047 //
1048 // XNameReplace methods.
1049 //
1050 //=========================================================================
1051 
1052 // virtual
replaceByName(const rtl::OUString & aName,const uno::Any & aElement)1053 void SAL_CALL HierarchyDataAccess::replaceByName( const rtl::OUString & aName,
1054                                                   const uno::Any & aElement )
1055     throw ( lang::IllegalArgumentException,
1056             container::NoSuchElementException,
1057             lang::WrappedTargetException,
1058             uno::RuntimeException )
1059 {
1060     uno::Reference< container::XNameReplace > xOrig
1061         = ENSURE_ORIG_INTERFACE( container::XNameReplace, NR );
1062 
1063     OSL_ENSURE( xOrig.is(),
1064         "HierarchyDataAccess : Data source is not an XNameReplace!" );
1065     xOrig->replaceByName( aName, aElement );
1066 }
1067 
1068 //=========================================================================
1069 //
1070 // XChangesBatch methods.
1071 //
1072 //=========================================================================
1073 
1074 // virtual
commitChanges()1075 void SAL_CALL HierarchyDataAccess::commitChanges()
1076     throw ( lang::WrappedTargetException, uno::RuntimeException )
1077 {
1078     uno::Reference< util::XChangesBatch > xOrig
1079         = ENSURE_ORIG_INTERFACE( util::XChangesBatch, CB );
1080 
1081     OSL_ENSURE( xOrig.is(),
1082         "HierarchyDataAccess : Data source is not an XChangesBatch!" );
1083     xOrig->commitChanges();
1084 }
1085 
1086 //=========================================================================
1087 // virtual
hasPendingChanges()1088 sal_Bool SAL_CALL HierarchyDataAccess::hasPendingChanges()
1089     throw ( uno::RuntimeException )
1090 {
1091     uno::Reference< util::XChangesBatch > xOrig
1092         = ENSURE_ORIG_INTERFACE( util::XChangesBatch, CB );
1093 
1094     OSL_ENSURE( xOrig.is(),
1095         "HierarchyDataAccess : Data source is not an XChangesBatch!" );
1096     return xOrig->hasPendingChanges();
1097 }
1098 
1099 //=========================================================================
1100 // virtual
1101 uno::Sequence< util::ElementChange > SAL_CALL
getPendingChanges()1102 HierarchyDataAccess::getPendingChanges()
1103     throw ( uno::RuntimeException )
1104 {
1105     uno::Reference< util::XChangesBatch > xOrig
1106         = ENSURE_ORIG_INTERFACE( util::XChangesBatch, CB );
1107 
1108     OSL_ENSURE( xOrig.is(),
1109         "HierarchyDataAccess : Data source is not an XChangesBatch!" );
1110     return xOrig->getPendingChanges();
1111 }
1112 
1113