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 <osl/mutex.hxx>
21 #include <comphelper/sequence.hxx>
22 #include <cppuhelper/weak.hxx>
23 #include <cppuhelper/implbase.hxx>
24 #include <cppuhelper/implbase4.hxx>
25 #include <cppuhelper/supportsservice.hxx>
26 #include <rtl/ref.hxx>
27 
28 #include <com/sun/star/registry/XSimpleRegistry.hpp>
29 #include <com/sun/star/lang/XServiceInfo.hpp>
30 #include <com/sun/star/lang/XInitialization.hpp>
31 #include <com/sun/star/container/XEnumerationAccess.hpp>
32 
33 namespace com::sun::star::uno { class XComponentContext; }
34 
35 using namespace css::uno;
36 using namespace css::registry;
37 using namespace css::lang;
38 using namespace css::container;
39 using namespace cppu;
40 using namespace osl;
41 
42 namespace {
43 
44 class NestedRegistryImpl    : public WeakAggImplHelper4 < XSimpleRegistry, XInitialization, XServiceInfo, XEnumerationAccess >
45 {
46 public:
47     NestedRegistryImpl( );
48 
49     // XServiceInfo
50     virtual OUString SAL_CALL getImplementationName(  ) override;
51     virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
52     virtual Sequence< OUString > SAL_CALL getSupportedServiceNames(  ) override;
53 
54     // XInitialization
55     virtual void SAL_CALL initialize( const Sequence< Any >& aArguments ) override;
56 
57     // XSimpleRegistry
58     virtual OUString SAL_CALL getURL() override;
59     virtual void SAL_CALL open( const OUString& rURL, sal_Bool bReadOnly, sal_Bool bCreate ) override;
60     virtual sal_Bool SAL_CALL isValid(  ) override;
61     virtual void SAL_CALL close(  ) override;
62     virtual void SAL_CALL destroy(  ) override;
63     virtual Reference< XRegistryKey > SAL_CALL getRootKey(  ) override;
64     virtual sal_Bool SAL_CALL isReadOnly(  ) override;
65     virtual void SAL_CALL mergeKey( const OUString& aKeyName, const OUString& aUrl ) override;
66 
67     // XEnumerationAccess
68     virtual Reference< XEnumeration > SAL_CALL createEnumeration(  ) override;
69     virtual Type SAL_CALL getElementType(  ) override;
70     virtual sal_Bool SAL_CALL hasElements(  ) override;
71 
72     friend class NestedKeyImpl;
73 protected:
74     Mutex                       m_mutex;
75     sal_uInt32                  m_state;
76     Reference<XSimpleRegistry>  m_localReg;
77     Reference<XSimpleRegistry>  m_defaultReg;
78 
79 };
80 
81 
82 // class NestedKeyImpl the implementation of interface XRegistryKey
83 
84 class NestedKeyImpl : public WeakImplHelper< XRegistryKey >
85 {
86 public:
87     NestedKeyImpl( NestedRegistryImpl* pDefaultRegistry,
88                    Reference<XRegistryKey>& localKey,
89                    Reference<XRegistryKey>& defaultKey);
90 
91     NestedKeyImpl( const OUString& aKeyName,
92                     NestedKeyImpl* pKey);
93 
94     // XRegistryKey
95     virtual OUString SAL_CALL getKeyName() override;
96     virtual sal_Bool SAL_CALL isReadOnly(  ) override;
97     virtual sal_Bool SAL_CALL isValid(  ) override;
98     virtual RegistryKeyType SAL_CALL getKeyType( const OUString& rKeyName ) override;
99     virtual RegistryValueType SAL_CALL getValueType(  ) override;
100     virtual sal_Int32 SAL_CALL getLongValue(  ) override;
101     virtual void SAL_CALL setLongValue( sal_Int32 value ) override;
102     virtual Sequence< sal_Int32 > SAL_CALL getLongListValue(  ) override;
103     virtual void SAL_CALL setLongListValue( const css::uno::Sequence< sal_Int32 >& seqValue ) override;
104     virtual OUString SAL_CALL getAsciiValue(  ) override;
105     virtual void SAL_CALL setAsciiValue( const OUString& value ) override;
106     virtual Sequence< OUString > SAL_CALL getAsciiListValue(  ) override;
107     virtual void SAL_CALL setAsciiListValue( const css::uno::Sequence< OUString >& seqValue ) override;
108     virtual OUString SAL_CALL getStringValue(  ) override;
109     virtual void SAL_CALL setStringValue( const OUString& value ) override;
110     virtual Sequence< OUString > SAL_CALL getStringListValue(  ) override;
111     virtual void SAL_CALL setStringListValue( const css::uno::Sequence< OUString >& seqValue ) override;
112     virtual Sequence< sal_Int8 > SAL_CALL getBinaryValue(  ) override;
113     virtual void SAL_CALL setBinaryValue( const css::uno::Sequence< sal_Int8 >& value ) override;
114     virtual Reference< XRegistryKey > SAL_CALL openKey( const OUString& aKeyName ) override;
115     virtual Reference< XRegistryKey > SAL_CALL createKey( const OUString& aKeyName ) override;
116     virtual void SAL_CALL closeKey(  ) override;
117     virtual void SAL_CALL deleteKey( const OUString& rKeyName ) override;
118     virtual Sequence< Reference< XRegistryKey > > SAL_CALL openKeys(  ) override;
119     virtual Sequence< OUString > SAL_CALL getKeyNames(  ) override;
120     virtual sal_Bool SAL_CALL createLink( const OUString& aLinkName, const OUString& aLinkTarget ) override;
121     virtual void SAL_CALL deleteLink( const OUString& rLinkName ) override;
122     virtual OUString SAL_CALL getLinkTarget( const OUString& rLinkName ) override;
123     virtual OUString SAL_CALL getResolvedName( const OUString& aKeyName ) override;
124 
125 protected:
126     void        computeChanges();
127     OUString    computeName(const OUString& name);
128 
129     OUString                    m_name;
130     sal_uInt32                  m_state;
131     rtl::Reference<NestedRegistryImpl> m_xRegistry;
132     Reference<XRegistryKey>     m_localKey;
133     Reference<XRegistryKey>     m_defaultKey;
134 };
135 
136 
NestedKeyImpl(NestedRegistryImpl * pDefaultRegistry,Reference<XRegistryKey> & localKey,Reference<XRegistryKey> & defaultKey)137 NestedKeyImpl::NestedKeyImpl( NestedRegistryImpl* pDefaultRegistry,
138                               Reference<XRegistryKey>& localKey,
139                               Reference<XRegistryKey>& defaultKey )
140     : m_xRegistry(pDefaultRegistry)
141 {
142     m_localKey = localKey;
143     m_defaultKey = defaultKey;
144 
145     if (m_localKey.is())
146     {
147         m_name = m_localKey->getKeyName();
148     }
149     else if (m_defaultKey.is())
150     {
151         m_name = m_defaultKey->getKeyName();
152     }
153 
154     m_state = m_xRegistry->m_state;
155 }
156 
157 
NestedKeyImpl(const OUString & rKeyName,NestedKeyImpl * pKey)158 NestedKeyImpl::NestedKeyImpl( const OUString& rKeyName,
159                               NestedKeyImpl* pKey)
160     : m_xRegistry(pKey->m_xRegistry)
161 {
162     if (pKey->m_localKey.is() && pKey->m_localKey->isValid())
163     {
164         m_localKey = pKey->m_localKey->openKey(rKeyName);
165     }
166     if (pKey->m_defaultKey.is() && pKey->m_defaultKey->isValid())
167     {
168         m_defaultKey = pKey->m_defaultKey->openKey(rKeyName);
169     }
170 
171     if (m_localKey.is())
172     {
173         m_name = m_localKey->getKeyName();
174     }
175     else if (m_defaultKey.is())
176     {
177         m_name = m_defaultKey->getKeyName();
178     }
179 
180     m_state = m_xRegistry->m_state;
181 }
182 
computeChanges()183 void NestedKeyImpl::computeChanges()
184 {
185     Guard< Mutex > aGuard( m_xRegistry->m_mutex );
186     if ( m_state == m_xRegistry->m_state )
187         return;
188 
189     Reference<XRegistryKey> rootKey(m_xRegistry->m_localReg->getRootKey());
190 
191     Reference<XRegistryKey> tmpKey = rootKey->openKey(m_name);
192 
193     if ( tmpKey.is() )
194     {
195         m_localKey = rootKey->openKey(m_name);
196     }
197 
198     m_state = m_xRegistry->m_state;
199 }
200 
201 
202 // NestedKey_Impl::computeName()
203 
computeName(const OUString & name)204 OUString NestedKeyImpl::computeName(const OUString& name)
205 {
206     OUString resLocalName, resDefaultName;
207 
208     Guard< Mutex > aGuard( m_xRegistry->m_mutex );
209     try
210     {
211         if ( m_localKey.is() && m_localKey->isValid() )
212         {
213             resLocalName = m_localKey->getResolvedName(name);
214         }
215         else if ( m_defaultKey.is() && m_defaultKey->isValid() )
216         {
217             return m_defaultKey->getResolvedName(name);
218         }
219 
220         if ( !resLocalName.isEmpty() && m_xRegistry->m_defaultReg->isValid() )
221         {
222             Reference<XRegistryKey> localRoot(m_xRegistry->m_localReg->getRootKey());
223             Reference<XRegistryKey> defaultRoot(m_xRegistry->m_defaultReg->getRootKey());
224 
225             resDefaultName = defaultRoot->getResolvedName(resLocalName);
226 
227             sal_uInt32 count = 100;
228 
229             while (resLocalName != resDefaultName && count > 0)
230             {
231                 count--;
232 
233                 if (resLocalName.isEmpty() || resDefaultName.isEmpty())
234                     throw InvalidRegistryException();
235 
236                 resLocalName = localRoot->getResolvedName(resDefaultName);
237                 resDefaultName = defaultRoot->getResolvedName(resLocalName);
238             }
239         }
240     }
241     catch(InvalidRegistryException& )
242     {
243     }
244 
245     return resLocalName;
246 }
247 
248 
getKeyName()249 OUString SAL_CALL NestedKeyImpl::getKeyName()
250 {
251     Guard< Mutex > aGuard( m_xRegistry->m_mutex );
252     return m_name;
253 }
254 
255 
isReadOnly()256 sal_Bool SAL_CALL NestedKeyImpl::isReadOnly(  )
257 {
258     Guard< Mutex > aGuard( m_xRegistry->m_mutex );
259     computeChanges();
260 
261     if ( !m_localKey.is() || !m_localKey->isValid() )
262         throw InvalidRegistryException();
263 
264     return m_localKey->isReadOnly();
265 }
266 
267 
isValid()268 sal_Bool SAL_CALL NestedKeyImpl::isValid(  )
269 {
270     Guard< Mutex > aGuard( m_xRegistry->m_mutex );
271     return ((m_localKey.is() && m_localKey->isValid()) ||
272             (m_defaultKey.is() && m_defaultKey->isValid()) );
273 }
274 
275 
getKeyType(const OUString & rKeyName)276 RegistryKeyType SAL_CALL NestedKeyImpl::getKeyType( const OUString& rKeyName )
277 {
278     Guard< Mutex > aGuard( m_xRegistry->m_mutex );
279     computeChanges();
280 
281     if ( m_localKey.is() && m_localKey->isValid() )
282     {
283         return m_localKey->getKeyType(rKeyName);
284     }
285     else if ( m_defaultKey.is() && m_defaultKey->isValid() )
286     {
287         return m_defaultKey->getKeyType(rKeyName);
288     }
289 
290     return RegistryKeyType_KEY;
291 }
292 
293 
getValueType()294 RegistryValueType SAL_CALL NestedKeyImpl::getValueType(  )
295 {
296     Guard< Mutex > aGuard( m_xRegistry->m_mutex );
297     computeChanges();
298 
299     if ( m_localKey.is() && m_localKey->isValid() )
300     {
301         return m_localKey->getValueType();
302     }
303     else if ( m_defaultKey.is() && m_defaultKey->isValid() )
304     {
305         return m_defaultKey->getValueType();
306     }
307 
308     return RegistryValueType_NOT_DEFINED;
309 }
310 
311 
getLongValue()312 sal_Int32 SAL_CALL NestedKeyImpl::getLongValue(  )
313 {
314     Guard< Mutex > aGuard( m_xRegistry->m_mutex );
315     computeChanges();
316 
317     if ( m_localKey.is() && m_localKey->isValid() )
318     {
319         return m_localKey->getLongValue();
320     }
321     else if ( m_defaultKey.is() && m_defaultKey->isValid() )
322     {
323         return m_defaultKey->getLongValue();
324     }
325     else
326     {
327         throw InvalidRegistryException();
328     }
329 }
330 
331 
setLongValue(sal_Int32 value)332 void SAL_CALL NestedKeyImpl::setLongValue( sal_Int32 value )
333 {
334     Guard< Mutex > aGuard( m_xRegistry->m_mutex );
335     computeChanges();
336 
337     if ( m_localKey.is() && m_localKey->isValid() )
338     {
339         m_localKey->setLongValue(value);
340     }
341     else if ( m_defaultKey.is() && m_defaultKey->isValid() )
342     {
343         Reference<XRegistryKey> rootKey(m_xRegistry->m_localReg->getRootKey());
344         m_localKey = rootKey->createKey(m_name);
345         m_localKey->setLongValue(value);
346         m_state = m_xRegistry->m_state++;
347     }
348     else
349     {
350         throw InvalidRegistryException();
351     }
352 }
353 
354 
getLongListValue()355 Sequence< sal_Int32 > SAL_CALL NestedKeyImpl::getLongListValue(  )
356 {
357     Guard< Mutex > aGuard( m_xRegistry->m_mutex );
358     computeChanges();
359 
360     if ( m_localKey.is() && m_localKey->isValid() )
361     {
362         return m_localKey->getLongListValue();
363     }
364     else if ( m_defaultKey.is() && m_defaultKey->isValid() )
365     {
366         return m_defaultKey->getLongListValue();
367     }
368     else
369     {
370         throw InvalidRegistryException();
371     }
372 }
373 
374 
setLongListValue(const Sequence<sal_Int32> & seqValue)375 void SAL_CALL NestedKeyImpl::setLongListValue( const Sequence< sal_Int32 >& seqValue )
376 {
377     Guard< Mutex > aGuard( m_xRegistry->m_mutex );
378     computeChanges();
379 
380     if ( m_localKey.is() && m_localKey->isValid() )
381     {
382         m_localKey->setLongListValue(seqValue);
383     }
384     else if ( m_defaultKey.is() && m_defaultKey->isValid() )
385     {
386         Reference<XRegistryKey> rootKey(m_xRegistry->m_localReg->getRootKey());
387         m_localKey = rootKey->createKey(m_name);
388         m_localKey->setLongListValue(seqValue);
389         m_state = m_xRegistry->m_state++;
390     }
391     else
392     {
393         throw InvalidRegistryException();
394     }
395 }
396 
397 
getAsciiValue()398 OUString SAL_CALL NestedKeyImpl::getAsciiValue(  )
399 {
400     Guard< Mutex > aGuard( m_xRegistry->m_mutex );
401     computeChanges();
402 
403     if ( m_localKey.is() && m_localKey->isValid() )
404     {
405         return m_localKey->getAsciiValue();
406     }
407     else if ( m_defaultKey.is() && m_defaultKey->isValid() )
408     {
409         return m_defaultKey->getAsciiValue();
410     }
411     else
412     {
413         throw InvalidRegistryException();
414     }
415 }
416 
417 
setAsciiValue(const OUString & value)418 void SAL_CALL NestedKeyImpl::setAsciiValue( const OUString& value )
419 {
420     Guard< Mutex > aGuard( m_xRegistry->m_mutex );
421     computeChanges();
422 
423     if ( m_localKey.is() && m_localKey->isValid() )
424     {
425         m_localKey->setAsciiValue(value);
426     }
427     else if ( m_defaultKey.is() && m_defaultKey->isValid() )
428     {
429         Reference<XRegistryKey> rootKey(m_xRegistry->m_localReg->getRootKey());
430         m_localKey = rootKey->createKey(m_name);
431         m_localKey->setAsciiValue(value);
432         m_state = m_xRegistry->m_state++;
433     }
434     else
435     {
436         throw InvalidRegistryException();
437     }
438 }
439 
440 
getAsciiListValue()441 Sequence< OUString > SAL_CALL NestedKeyImpl::getAsciiListValue(  )
442 {
443     Guard< Mutex > aGuard( m_xRegistry->m_mutex );
444     computeChanges();
445 
446     if ( m_localKey.is() && m_localKey->isValid() )
447     {
448         return m_localKey->getAsciiListValue();
449     }
450     else if ( m_defaultKey.is() && m_defaultKey->isValid() )
451     {
452         return m_defaultKey->getAsciiListValue();
453     }
454     else
455     {
456         throw InvalidRegistryException();
457     }
458 }
459 
460 
setAsciiListValue(const Sequence<OUString> & seqValue)461 void SAL_CALL NestedKeyImpl::setAsciiListValue( const Sequence< OUString >& seqValue )
462 {
463     Guard< Mutex > aGuard( m_xRegistry->m_mutex );
464     computeChanges();
465 
466     if ( m_localKey.is() && m_localKey->isValid() )
467     {
468         m_localKey->setAsciiListValue(seqValue);
469     }
470     else if ( m_defaultKey.is() && m_defaultKey->isValid() )
471     {
472         Reference<XRegistryKey> rootKey(m_xRegistry->m_localReg->getRootKey());
473         m_localKey = rootKey->createKey(m_name);
474         m_localKey->setAsciiListValue(seqValue);
475         m_state = m_xRegistry->m_state++;
476     }
477     else
478     {
479         throw InvalidRegistryException();
480     }
481 }
482 
483 
getStringValue()484 OUString SAL_CALL NestedKeyImpl::getStringValue(  )
485 {
486     Guard< Mutex > aGuard( m_xRegistry->m_mutex );
487     computeChanges();
488 
489     if ( m_localKey.is() && m_localKey->isValid() )
490     {
491         return m_localKey->getStringValue();
492     }
493     else if ( m_defaultKey.is() && m_defaultKey->isValid() )
494     {
495         return m_defaultKey->getStringValue();
496     }
497     else
498     {
499         throw InvalidRegistryException();
500     }
501 }
502 
503 
setStringValue(const OUString & value)504 void SAL_CALL NestedKeyImpl::setStringValue( const OUString& value )
505 {
506     Guard< Mutex > aGuard( m_xRegistry->m_mutex );
507     computeChanges();
508 
509     if ( m_localKey.is() && m_localKey->isValid() )
510     {
511         m_localKey->setStringValue(value);
512     }
513     else if ( m_defaultKey.is() && m_defaultKey->isValid() )
514     {
515         Reference<XRegistryKey> rootKey(m_xRegistry->m_localReg->getRootKey());
516         m_localKey = rootKey->createKey(m_name);
517         m_localKey->setStringValue(value);
518         m_state = m_xRegistry->m_state++;
519     }
520     else
521     {
522         throw InvalidRegistryException();
523     }
524 }
525 
526 
getStringListValue()527 Sequence< OUString > SAL_CALL NestedKeyImpl::getStringListValue(  )
528 {
529     Guard< Mutex > aGuard( m_xRegistry->m_mutex );
530     computeChanges();
531 
532     if ( m_localKey.is() && m_localKey->isValid() )
533     {
534         return m_localKey->getStringListValue();
535     }
536     else if ( m_defaultKey.is() && m_defaultKey->isValid() )
537     {
538         return m_defaultKey->getStringListValue();
539     }
540     else
541     {
542         throw InvalidRegistryException();
543     }
544 }
545 
546 
setStringListValue(const Sequence<OUString> & seqValue)547 void SAL_CALL NestedKeyImpl::setStringListValue( const Sequence< OUString >& seqValue )
548 {
549     Guard< Mutex > aGuard( m_xRegistry->m_mutex );
550     computeChanges();
551 
552     if ( m_localKey.is() && m_localKey->isValid() )
553     {
554         m_localKey->setStringListValue(seqValue);
555     }
556     else if ( m_defaultKey.is() && m_defaultKey->isValid() )
557     {
558         Reference<XRegistryKey> rootKey(m_xRegistry->m_localReg->getRootKey());
559         m_localKey = rootKey->createKey(m_name);
560         m_localKey->setStringListValue(seqValue);
561         m_state = m_xRegistry->m_state++;
562     }
563     else
564     {
565         throw InvalidRegistryException();
566     }
567 }
568 
569 
getBinaryValue()570 Sequence< sal_Int8 > SAL_CALL NestedKeyImpl::getBinaryValue(  )
571 {
572     Guard< Mutex > aGuard( m_xRegistry->m_mutex );
573     computeChanges();
574 
575     if ( m_localKey.is() && m_localKey->isValid() )
576     {
577         return m_localKey->getBinaryValue();
578     }
579     else if ( m_defaultKey.is() && m_defaultKey->isValid() )
580     {
581         return m_defaultKey->getBinaryValue();
582     }
583     else
584     {
585         throw InvalidRegistryException();
586     }
587 }
588 
589 
setBinaryValue(const Sequence<sal_Int8> & value)590 void SAL_CALL NestedKeyImpl::setBinaryValue( const Sequence< sal_Int8 >& value )
591 {
592     Guard< Mutex > aGuard( m_xRegistry->m_mutex );
593     computeChanges();
594 
595     if ( m_localKey.is() && m_localKey->isValid() )
596     {
597         m_localKey->setBinaryValue(value);
598     }
599     else if ( m_defaultKey.is() && m_defaultKey->isValid() )
600     {
601         Reference<XRegistryKey> rootKey(m_xRegistry->m_localReg->getRootKey());
602         m_localKey = rootKey->createKey(m_name);
603         m_localKey->setBinaryValue(value);
604         m_state = m_xRegistry->m_state++;
605     }
606     else
607     {
608         throw InvalidRegistryException();
609     }
610 }
611 
612 
openKey(const OUString & aKeyName)613 Reference< XRegistryKey > SAL_CALL NestedKeyImpl::openKey( const OUString& aKeyName )
614 {
615     Guard< Mutex > aGuard( m_xRegistry->m_mutex );
616     if ( !m_localKey.is() && !m_defaultKey.is() )
617     {
618         throw InvalidRegistryException();
619     }
620 
621     OUString resolvedName = computeName(aKeyName);
622 
623     if ( resolvedName.isEmpty() )
624         throw InvalidRegistryException();
625 
626     Reference<XRegistryKey> localKey, defaultKey;
627 
628     if ( m_localKey.is() && m_localKey->isValid() )
629     {
630         localKey = m_xRegistry->m_localReg->getRootKey()->openKey(resolvedName);
631     }
632     if ( m_defaultKey.is() && m_defaultKey->isValid() )
633     {
634         defaultKey = m_xRegistry->m_defaultReg->getRootKey()->openKey(resolvedName);
635     }
636 
637     if ( localKey.is() || defaultKey.is() )
638     {
639         return new NestedKeyImpl(m_xRegistry.get(), localKey, defaultKey);
640     }
641     else
642     {
643         return Reference<XRegistryKey>();
644     }
645 }
646 
647 
createKey(const OUString & aKeyName)648 Reference< XRegistryKey > SAL_CALL NestedKeyImpl::createKey( const OUString& aKeyName )
649 {
650     Guard< Mutex > aGuard( m_xRegistry->m_mutex );
651     if ( (!m_localKey.is() && !m_defaultKey.is()) ||
652          (m_localKey.is() && m_localKey->isReadOnly()) )
653     {
654         throw InvalidRegistryException();
655     }
656 
657     OUString resolvedName = computeName(aKeyName);
658 
659     if ( resolvedName.isEmpty() )
660         throw InvalidRegistryException();
661 
662     if ( m_localKey.is() && m_localKey->isValid() )
663     {
664         Reference<XRegistryKey> localKey, defaultKey;
665 
666         localKey = m_xRegistry->m_localReg->getRootKey()->createKey(resolvedName);
667         if ( localKey.is() )
668         {
669             if ( m_defaultKey.is() && m_defaultKey->isValid() )
670             {
671                 defaultKey = m_xRegistry->m_defaultReg->getRootKey()->openKey(resolvedName);
672             }
673 
674             m_state = m_xRegistry->m_state++;
675 
676             return new NestedKeyImpl(m_xRegistry.get(), localKey, defaultKey);
677         }
678     }
679     else
680     {
681         Reference<XRegistryKey> localKey, defaultKey;
682 
683         if ( m_defaultKey.is() && m_defaultKey->isValid() )
684         {
685             Reference<XRegistryKey> rootKey(m_xRegistry->m_localReg->getRootKey());
686             m_localKey = rootKey->createKey(m_name);
687 
688             localKey = m_xRegistry->m_localReg->getRootKey()->createKey(resolvedName);
689 
690             if ( localKey.is() )
691             {
692                 defaultKey = m_xRegistry->m_defaultReg->getRootKey()->openKey(resolvedName);
693 
694                 m_state = m_xRegistry->m_state++;
695 
696                 return new NestedKeyImpl(m_xRegistry.get(), localKey, defaultKey);
697             }
698         }
699     }
700 
701     return Reference<XRegistryKey>();
702 }
703 
704 
closeKey()705 void SAL_CALL NestedKeyImpl::closeKey(  )
706 {
707     Guard< Mutex > aGuard( m_xRegistry->m_mutex );
708     if ( m_localKey.is() && m_localKey->isValid() )
709     {
710         m_localKey->closeKey();
711     }
712     if ( m_defaultKey.is() && m_defaultKey->isValid() )
713     {
714         m_defaultKey->closeKey();
715     }
716 }
717 
718 
deleteKey(const OUString & rKeyName)719 void SAL_CALL NestedKeyImpl::deleteKey( const OUString& rKeyName )
720 {
721     Guard< Mutex > aGuard( m_xRegistry->m_mutex );
722     if ( !m_localKey.is() || !m_localKey->isValid() ||
723          m_localKey->isReadOnly() )
724     {
725         throw InvalidRegistryException();
726     }
727 
728     OUString resolvedName = computeName(rKeyName);
729 
730     if ( resolvedName.isEmpty() )
731     {
732         throw InvalidRegistryException();
733     }
734 
735     m_xRegistry->m_localReg->getRootKey()->deleteKey(resolvedName);
736 }
737 
738 
openKeys()739 Sequence< Reference< XRegistryKey > > SAL_CALL NestedKeyImpl::openKeys(  )
740 {
741     Guard< Mutex > aGuard( m_xRegistry->m_mutex );
742     if ( !m_localKey.is() && !m_defaultKey.is() )
743     {
744         throw InvalidRegistryException();
745     }
746 
747     Sequence<OUString> localSeq, defaultSeq;
748 
749     if ( m_localKey.is() && m_localKey->isValid() )
750     {
751         localSeq = m_localKey->getKeyNames();
752     }
753     if ( m_defaultKey.is() && m_defaultKey->isValid() )
754     {
755         defaultSeq = m_defaultKey->getKeyNames();
756     }
757 
758     std::vector< Reference<XRegistryKey> > retVec;
759     retVec.reserve(localSeq.getLength() + defaultSeq.getLength());
760 
761     auto lKeyNameToRegKey = [this](const OUString& rName) -> Reference<XRegistryKey> {
762         sal_Int32 lastIndex = rName.lastIndexOf('/');
763         OUString name = rName.copy(lastIndex);
764         return new NestedKeyImpl(name, this);
765     };
766 
767     for (const auto& rKeyName : std::as_const(localSeq))
768         retVec.push_back(lKeyNameToRegKey(rKeyName));
769 
770     for (const auto& rKeyName : std::as_const(defaultSeq))
771     {
772         if ( comphelper::findValue(localSeq, rKeyName) == -1 )
773         {
774             retVec.push_back(lKeyNameToRegKey(rKeyName));
775         }
776     }
777 
778     return comphelper::containerToSequence(retVec);
779 }
780 
781 
getKeyNames()782 Sequence< OUString > SAL_CALL NestedKeyImpl::getKeyNames(  )
783 {
784     Guard< Mutex > aGuard( m_xRegistry->m_mutex );
785     if ( !m_localKey.is() && !m_defaultKey.is() )
786     {
787         throw InvalidRegistryException();
788     }
789 
790     Sequence<OUString> localSeq, defaultSeq;
791 
792     if ( m_localKey.is() && m_localKey->isValid() )
793     {
794         localSeq = m_localKey->getKeyNames();
795     }
796     if ( m_defaultKey.is() && m_defaultKey->isValid() )
797     {
798         defaultSeq = m_defaultKey->getKeyNames();
799     }
800 
801     return comphelper::combineSequences(localSeq, defaultSeq);
802 }
803 
804 
createLink(const OUString & aLinkName,const OUString & aLinkTarget)805 sal_Bool SAL_CALL NestedKeyImpl::createLink( const OUString& aLinkName, const OUString& aLinkTarget )
806 {
807     Guard< Mutex > aGuard( m_xRegistry->m_mutex );
808 
809     bool isCreated = false;
810     if ( !m_localKey.is() && !m_defaultKey.is() )
811     {
812         throw InvalidRegistryException();
813     }
814 
815     OUString    linkName;
816     OUString    resolvedName;
817     sal_Int32   lastIndex = aLinkName.lastIndexOf('/');
818 
819     if ( lastIndex > 0 )
820     {
821         linkName = aLinkName.copy(0, lastIndex);
822 
823         resolvedName = computeName(linkName);
824 
825         if ( resolvedName.isEmpty() )
826         {
827             throw InvalidRegistryException();
828         }
829 
830         resolvedName += aLinkName.copy(lastIndex);
831     }
832     else
833     {
834         if ( lastIndex == 0 )
835             resolvedName = m_name + aLinkName;
836         else
837             resolvedName = m_name + "/" + aLinkName;
838     }
839 
840     if ( m_localKey.is() && m_localKey->isValid() )
841     {
842         isCreated = m_xRegistry->m_localReg->getRootKey()->createLink(resolvedName, aLinkTarget);
843     }
844     else
845     {
846         if ( m_defaultKey.is() && m_defaultKey->isValid() )
847         {
848             Reference<XRegistryKey> rootKey(m_xRegistry->m_localReg->getRootKey());
849             m_localKey = rootKey->createKey(m_name);
850 
851             isCreated = m_xRegistry->m_localReg->getRootKey()->createLink(resolvedName, aLinkTarget);
852         }
853     }
854 
855     if ( isCreated )
856         m_state = m_xRegistry->m_state++;
857 
858     return isCreated;
859 }
860 
861 
deleteLink(const OUString & rLinkName)862 void SAL_CALL NestedKeyImpl::deleteLink( const OUString& rLinkName )
863 {
864     Guard< Mutex > aGuard( m_xRegistry->m_mutex );
865     if ( !m_localKey.is() && !m_defaultKey.is() )
866     {
867         throw InvalidRegistryException();
868     }
869 
870     OUString    linkName;
871     OUString    resolvedName;
872     sal_Int32   lastIndex = rLinkName.lastIndexOf('/');
873 
874     if ( lastIndex > 0 )
875     {
876         linkName = rLinkName.copy(0, lastIndex);
877 
878         resolvedName = computeName(linkName);
879 
880         if ( resolvedName.isEmpty() )
881         {
882             throw InvalidRegistryException();
883         }
884 
885         resolvedName += rLinkName.copy(lastIndex);
886     }
887     else
888     {
889         if ( lastIndex == 0 )
890             resolvedName = m_name + rLinkName;
891         else
892             resolvedName = m_name + "/" + rLinkName;
893     }
894 
895     if ( !m_localKey.is() || !m_localKey->isValid() ||
896          m_localKey->isReadOnly() )
897     {
898         throw InvalidRegistryException();
899     }
900 
901     m_xRegistry->m_localReg->getRootKey()->deleteLink(resolvedName);
902 }
903 
904 
getLinkTarget(const OUString & rLinkName)905 OUString SAL_CALL NestedKeyImpl::getLinkTarget( const OUString& rLinkName )
906 {
907     Guard< Mutex > aGuard( m_xRegistry->m_mutex );
908     if ( !m_localKey.is() && !m_defaultKey.is() )
909     {
910         throw InvalidRegistryException();
911     }
912 
913     OUString    linkName;
914     OUString    resolvedName;
915     sal_Int32   lastIndex = rLinkName.lastIndexOf('/');
916 
917     if ( lastIndex > 0 )
918     {
919         linkName = rLinkName.copy(0, lastIndex);
920 
921         resolvedName = computeName(linkName);
922 
923         if ( resolvedName.isEmpty() )
924         {
925             throw InvalidRegistryException();
926         }
927 
928         resolvedName += rLinkName.copy(lastIndex);
929     }
930     else
931     {
932         if ( lastIndex == 0 )
933             resolvedName = m_name + rLinkName;
934         else
935             resolvedName = m_name + "/" + rLinkName;
936     }
937 
938     OUString linkTarget;
939     if ( m_localKey.is() && m_localKey->isValid() )
940     {
941         try
942         {
943             linkTarget = m_xRegistry->m_localReg->getRootKey()->getLinkTarget(resolvedName);
944             return linkTarget;
945         }
946         catch(InvalidRegistryException& )
947         {
948         }
949     }
950 
951     if ( m_defaultKey.is() && m_defaultKey->isValid() )
952         linkTarget = m_xRegistry->m_defaultReg->getRootKey()->getLinkTarget(resolvedName);
953 
954     return linkTarget;
955 }
956 
957 
getResolvedName(const OUString & aKeyName)958 OUString SAL_CALL NestedKeyImpl::getResolvedName( const OUString& aKeyName )
959 {
960     Guard< Mutex > aGuard( m_xRegistry->m_mutex );
961     if ( !m_localKey.is() && !m_defaultKey.is() )
962     {
963         throw InvalidRegistryException();
964     }
965 
966     OUString resolvedName = computeName(aKeyName);
967 
968     if ( resolvedName.isEmpty() )
969     {
970         throw InvalidRegistryException();
971     }
972 
973     return resolvedName;
974 }
975 
976 
977 // DefaultRegistry Implementation
978 
979 
NestedRegistryImpl()980 NestedRegistryImpl::NestedRegistryImpl( )
981     : m_state(0)
982 {}
983 
984 class RegistryEnumueration : public WeakImplHelper< XEnumeration >
985 {
986 public:
RegistryEnumueration(const Reference<XSimpleRegistry> & r1,const Reference<XSimpleRegistry> & r2)987     RegistryEnumueration(
988         const Reference< XSimpleRegistry > &r1,
989         const Reference< XSimpleRegistry > &r2 )
990         : m_xReg1( r1 ) , m_xReg2( r2 )
991         {}
992 public:
993     virtual sal_Bool SAL_CALL hasMoreElements(  ) override;
994     virtual Any SAL_CALL nextElement(  ) override;
995 
996 private:
997     Reference< XSimpleRegistry > m_xReg1;
998     Reference< XSimpleRegistry > m_xReg2;
999 };
1000 
hasMoreElements()1001 sal_Bool RegistryEnumueration::hasMoreElements(  )
1002 {
1003     return m_xReg1.is() || m_xReg2.is();
1004 }
1005 
nextElement()1006 Any RegistryEnumueration::nextElement(  )
1007 {
1008     Any a;
1009     if( m_xReg1.is() )
1010     {
1011         a <<= m_xReg1;
1012         m_xReg1.clear();
1013     }
1014     else if( m_xReg2.is() )
1015     {
1016         a <<= m_xReg2;
1017         m_xReg2.clear();
1018     }
1019     else
1020     {
1021         throw NoSuchElementException( "NestedRegistry: no nextElement() !" );
1022     }
1023     return a;
1024 }
1025 
1026 
createEnumeration()1027 Reference< XEnumeration > NestedRegistryImpl::createEnumeration(  )
1028 {
1029     MutexGuard guard( m_mutex );
1030     return new RegistryEnumueration( m_localReg, m_defaultReg );
1031 }
1032 
getElementType()1033 Type NestedRegistryImpl::getElementType(  )
1034 {
1035     return cppu::UnoType<decltype(m_localReg)>::get();
1036 }
1037 
hasElements()1038 sal_Bool SAL_CALL NestedRegistryImpl::hasElements(  )
1039 {
1040     MutexGuard guard( m_mutex );
1041     return m_localReg.is() || m_defaultReg.is();
1042 }
1043 
1044 
getImplementationName()1045 OUString SAL_CALL NestedRegistryImpl::getImplementationName(  )
1046 {
1047     return "com.sun.star.comp.stoc.NestedRegistry";
1048 }
1049 
supportsService(const OUString & ServiceName)1050 sal_Bool SAL_CALL NestedRegistryImpl::supportsService( const OUString& ServiceName )
1051 {
1052     return cppu::supportsService(this, ServiceName);
1053 }
1054 
getSupportedServiceNames()1055 Sequence<OUString> SAL_CALL NestedRegistryImpl::getSupportedServiceNames(  )
1056 {
1057     Sequence< OUString > seqNames { "com.sun.star.registry.NestedRegistry" };
1058     return seqNames;
1059 }
1060 
1061 
initialize(const Sequence<Any> & aArguments)1062 void SAL_CALL NestedRegistryImpl::initialize( const Sequence< Any >& aArguments )
1063 {
1064     Guard< Mutex > aGuard( m_mutex );
1065     if ( (aArguments.getLength() == 2) &&
1066          (aArguments[0].getValueType().getTypeClass() == TypeClass_INTERFACE) &&
1067          (aArguments[1].getValueType().getTypeClass() == TypeClass_INTERFACE) )
1068     {
1069         aArguments[0] >>= m_localReg;
1070         aArguments[1] >>= m_defaultReg;
1071         if ( m_localReg == m_defaultReg )
1072             m_defaultReg.clear();
1073     }
1074 }
1075 
1076 
getURL()1077 OUString SAL_CALL NestedRegistryImpl::getURL()
1078 {
1079     Guard< Mutex > aGuard( m_mutex );
1080     try
1081     {
1082         if ( m_localReg.is() && m_localReg->isValid() )
1083             return m_localReg->getURL();
1084     }
1085     catch(InvalidRegistryException& )
1086     {
1087     }
1088 
1089     return OUString();
1090 }
1091 
1092 
open(const OUString &,sal_Bool,sal_Bool)1093 void SAL_CALL NestedRegistryImpl::open( const OUString&, sal_Bool, sal_Bool )
1094 {
1095     throw InvalidRegistryException(
1096             "the 'open' method is not specified for a nested registry" );
1097 }
1098 
1099 
isValid()1100 sal_Bool SAL_CALL NestedRegistryImpl::isValid(  )
1101 {
1102     Guard< Mutex > aGuard( m_mutex );
1103     try
1104     {
1105         if ( (m_localReg.is() && m_localReg->isValid()) ||
1106              (m_defaultReg.is() && m_defaultReg->isValid()) )
1107             return true;
1108     }
1109     catch(InvalidRegistryException& )
1110     {
1111     }
1112 
1113     return false;
1114 }
1115 
1116 
close()1117 void SAL_CALL NestedRegistryImpl::close(  )
1118 {
1119     Guard< Mutex > aGuard( m_mutex );
1120     if ( m_localReg.is() && m_localReg->isValid() )
1121     {
1122         m_localReg->close();
1123     }
1124     if ( m_defaultReg.is() && m_defaultReg->isValid() )
1125     {
1126         m_defaultReg->close();
1127     }
1128 }
1129 
1130 
destroy()1131 void SAL_CALL NestedRegistryImpl::destroy(  )
1132 {
1133     throw InvalidRegistryException(
1134             "the 'destroy' method is not specified for a nested registry" );
1135 }
1136 
1137 
getRootKey()1138 Reference< XRegistryKey > SAL_CALL NestedRegistryImpl::getRootKey(  )
1139 {
1140     Guard< Mutex > aGuard( m_mutex );
1141     if ( !m_localReg.is() || !m_localReg->isValid() )
1142     {
1143         throw InvalidRegistryException();
1144     }
1145 
1146     Reference<XRegistryKey> localKey, defaultKey;
1147 
1148     localKey = m_localReg->getRootKey();
1149 
1150     if ( localKey.is() )
1151     {
1152         if ( m_defaultReg.is() && m_defaultReg->isValid() )
1153         {
1154             defaultKey = m_defaultReg->getRootKey();
1155         }
1156 
1157         return new NestedKeyImpl(this, localKey, defaultKey);
1158     }
1159 
1160     return Reference<XRegistryKey>();
1161 }
1162 
1163 
isReadOnly()1164 sal_Bool SAL_CALL NestedRegistryImpl::isReadOnly(  )
1165 {
1166     Guard< Mutex > aGuard( m_mutex );
1167     try
1168     {
1169         if ( m_localReg.is() && m_localReg->isValid() )
1170             return m_localReg->isReadOnly();
1171     }
1172     catch(InvalidRegistryException& )
1173     {
1174     }
1175 
1176     return false;
1177 }
1178 
1179 
mergeKey(const OUString & aKeyName,const OUString & aUrl)1180 void SAL_CALL NestedRegistryImpl::mergeKey( const OUString& aKeyName, const OUString& aUrl )
1181 {
1182     Guard< Mutex > aGuard( m_mutex );
1183     if ( m_localReg.is() && m_localReg->isValid() )
1184     {
1185         m_localReg->mergeKey(aKeyName, aUrl);
1186 
1187         m_state++;
1188     }
1189 }
1190 
1191 } // namespace
1192 
1193 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
com_sun_star_comp_stoc_NestedRegistry_get_implementation(SAL_UNUSED_PARAMETER css::uno::XComponentContext *,css::uno::Sequence<css::uno::Any> const &)1194 com_sun_star_comp_stoc_NestedRegistry_get_implementation(
1195     SAL_UNUSED_PARAMETER css::uno::XComponentContext *,
1196     css::uno::Sequence<css::uno::Any> const &)
1197 {
1198     return cppu::acquire(new NestedRegistryImpl);
1199 }
1200 
1201 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1202