1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 
21 #include <vector>
22 
23 #include <osl/diagnose.h>
24 
25 #include <com/sun/star/registry/XRegistryKey.hpp>
26 
27 #include "mergekeys.hxx"
28 
29 using namespace ::osl;
30 using namespace css::uno;
31 using namespace ::com::sun::star;
32 
33 namespace stoc_impreg
34 {
35 
36 namespace {
37 
38 struct Link
39 {
40     OUString m_name;
41     OUString m_target;
42 
Linkstoc_impreg::__anone490d1720111::Link43     Link( OUString const & name, OUString const & target )
44         : m_name( name )
45         , m_target( target )
46         {}
47 };
48 
49 }
50 
51 typedef ::std::vector< Link > t_links;
52 
53 
mergeKeys(Reference<registry::XRegistryKey> const & xDest,Reference<registry::XRegistryKey> const & xSource,t_links & links)54 static void mergeKeys(
55     Reference< registry::XRegistryKey > const & xDest,
56     Reference< registry::XRegistryKey > const & xSource,
57     t_links & links )
58     // throw( registry::InvalidRegistryException, registry::MergeConflictException, RuntimeException )
59 {
60     if (!xSource.is() || !xSource->isValid()) {
61         throw registry::InvalidRegistryException(
62             "source key is null or invalid!" );
63     }
64     if (!xDest.is() || !xDest->isValid()) {
65         throw registry::InvalidRegistryException(
66             "destination key is null or invalid!" );
67     }
68 
69     // write value
70     switch (xSource->getValueType())
71     {
72     case registry::RegistryValueType_NOT_DEFINED:
73         break;
74     case registry::RegistryValueType_LONG:
75         xDest->setLongValue( xSource->getLongValue() );
76         break;
77     case registry::RegistryValueType_ASCII:
78         xDest->setAsciiValue( xSource->getAsciiValue() );
79         break;
80     case registry::RegistryValueType_STRING:
81         xDest->setStringValue( xSource->getStringValue() );
82         break;
83     case registry::RegistryValueType_BINARY:
84         xDest->setBinaryValue( xSource->getBinaryValue() );
85         break;
86     case registry::RegistryValueType_LONGLIST:
87         xDest->setLongListValue( xSource->getLongListValue() );
88         break;
89     case registry::RegistryValueType_ASCIILIST:
90         xDest->setAsciiListValue( xSource->getAsciiListValue() );
91         break;
92     case registry::RegistryValueType_STRINGLIST:
93         xDest->setStringListValue( xSource->getStringListValue() );
94         break;
95     default:
96         OSL_ASSERT(false);
97         break;
98     }
99 
100     // sub keys
101     Sequence< OUString > sourceKeys( xSource->getKeyNames() );
102     OUString const * pSourceKeys = sourceKeys.getConstArray();
103     for ( sal_Int32 nPos = sourceKeys.getLength(); nPos--; )
104     {
105         // key name
106         OUString name( pSourceKeys[ nPos ] );
107         sal_Int32 nSlash = name.lastIndexOf( '/' );
108         if (nSlash >= 0)
109         {
110             name = name.copy( nSlash +1 );
111         }
112 
113         if (xSource->getKeyType( name ) == registry::RegistryKeyType_KEY)
114         {
115             // try to open existing dest key or create new one
116             Reference< registry::XRegistryKey > xDestKey( xDest->createKey( name ) );
117             Reference< registry::XRegistryKey > xSourceKey( xSource->openKey( name ) );
118             mergeKeys( xDestKey, xSourceKey, links );
119             xSourceKey->closeKey();
120             xDestKey->closeKey();
121         }
122         else // link
123         {
124             // remove existing key
125             Reference< registry::XRegistryKey > xDestKey( xDest->openKey( name ) );
126             if (xDestKey.is() && xDestKey->isValid()) // something to remove
127             {
128                 xDestKey->closeKey();
129                 if (xDest->getKeyType( name ) == registry::RegistryKeyType_LINK)
130                 {
131                     xDest->deleteLink( name );
132                 }
133                 else
134                 {
135                     xDest->deleteKey( name );
136                 }
137             }
138 
139             links.push_back( Link(
140                 pSourceKeys[ nPos ], // abs path
141                 xSource->getResolvedName( name ) // abs resolved name
142                 ) );
143         }
144     }
145 }
146 
147 
mergeKeys(Reference<registry::XRegistryKey> const & xDest,Reference<registry::XRegistryKey> const & xSource)148 void mergeKeys(
149     Reference< registry::XRegistryKey > const & xDest,
150     Reference< registry::XRegistryKey > const & xSource )
151     // throw( registry::InvalidRegistryException, registry::MergeConflictException, RuntimeException )
152 {
153     if (!xDest.is() || !xDest->isValid()) {
154         throw registry::InvalidRegistryException(
155             "destination key is null or invalid!" );
156     }
157     if (xDest->isReadOnly())
158     {
159         throw registry::InvalidRegistryException(
160             "destination registry is read-only!  cannot merge!" );
161     }
162 
163     t_links links;
164     links.reserve( 16 );
165     mergeKeys( xDest, xSource, links );
166 
167     for ( size_t nPos = links.size(); nPos--; )
168     {
169         Link const & r = links[ nPos ];
170         OSL_VERIFY( xDest->createLink( r.m_name, r.m_target ) );
171     }
172 }
173 
174 }
175 
176 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
177