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