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_stoc.hxx"
30 
31 #include <vector>
32 
33 #include <com/sun/star/registry/XRegistryKey.hpp>
34 #include <com/sun/star/registry/MergeConflictException.hpp>
35 
36 #include "mergekeys.hxx"
37 
38 #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
39 
40 using namespace ::rtl;
41 using namespace ::osl;
42 using namespace ::com::sun::star::uno;
43 using namespace ::com::sun::star;
44 
45 namespace stoc_impreg
46 {
47 
48 struct Link
49 {
50     OUString m_name;
51     OUString m_target;
52 
53     inline Link( OUString const & name, OUString const & target )
54         : m_name( name )
55         , m_target( target )
56         {}
57 };
58 typedef ::std::vector< Link > t_links;
59 
60 //==================================================================================================
61 static void mergeKeys(
62     Reference< registry::XRegistryKey > const & xDest,
63     Reference< registry::XRegistryKey > const & xSource,
64     t_links & links )
65     // throw( registry::InvalidRegistryException, registry::MergeConflictException, RuntimeException )
66 {
67     if (!xSource.is() || !xSource->isValid()) {
68         throw registry::InvalidRegistryException(
69             OUSTR("source key is null or invalid!"),
70             Reference<XInterface>() );
71     }
72     if (!xDest.is() || !xDest->isValid()) {
73         throw registry::InvalidRegistryException(
74             OUSTR("destination key is null or invalid!"),
75             Reference<XInterface>() );
76     }
77 
78     // write value
79     switch (xSource->getValueType())
80     {
81     case registry::RegistryValueType_NOT_DEFINED:
82         break;
83     case registry::RegistryValueType_LONG:
84         xDest->setLongValue( xSource->getLongValue() );
85         break;
86     case registry::RegistryValueType_ASCII:
87         xDest->setAsciiValue( xSource->getAsciiValue() );
88         break;
89     case registry::RegistryValueType_STRING:
90         xDest->setStringValue( xSource->getStringValue() );
91         break;
92     case registry::RegistryValueType_BINARY:
93         xDest->setBinaryValue( xSource->getBinaryValue() );
94         break;
95     case registry::RegistryValueType_LONGLIST:
96         xDest->setLongListValue( xSource->getLongListValue() );
97         break;
98     case registry::RegistryValueType_ASCIILIST:
99         xDest->setAsciiListValue( xSource->getAsciiListValue() );
100         break;
101     case registry::RegistryValueType_STRINGLIST:
102         xDest->setStringListValue( xSource->getStringListValue() );
103         break;
104     default:
105         OSL_ASSERT(false);
106         break;
107     }
108 
109     // sub keys
110     Sequence< OUString > sourceKeys( xSource->getKeyNames() );
111     OUString const * pSourceKeys = sourceKeys.getConstArray();
112     for ( sal_Int32 nPos = sourceKeys.getLength(); nPos--; )
113     {
114         // key name
115         OUString name( pSourceKeys[ nPos ] );
116         sal_Int32 nSlash = name.lastIndexOf( '/' );
117         if (nSlash >= 0)
118         {
119             name = name.copy( nSlash +1 );
120         }
121 
122         if (xSource->getKeyType( name ) == registry::RegistryKeyType_KEY)
123         {
124             // try to open exisiting dest key or create new one
125             Reference< registry::XRegistryKey > xDestKey( xDest->createKey( name ) );
126             Reference< registry::XRegistryKey > xSourceKey( xSource->openKey( name ) );
127             mergeKeys( xDestKey, xSourceKey, links );
128             xSourceKey->closeKey();
129             xDestKey->closeKey();
130         }
131         else // link
132         {
133             // remove existing key
134             Reference< registry::XRegistryKey > xDestKey( xDest->openKey( name ) );
135             if (xDestKey.is() && xDestKey->isValid()) // something to remove
136             {
137                 xDestKey->closeKey();
138                 if (xDest->getKeyType( name ) == registry::RegistryKeyType_LINK)
139                 {
140                     xDest->deleteLink( name );
141                 }
142                 else
143                 {
144                     xDest->deleteKey( name );
145                 }
146             }
147 
148             links.push_back( Link(
149                 pSourceKeys[ nPos ], // abs path
150                 xSource->getResolvedName( name ) // abs resolved name
151                 ) );
152         }
153     }
154 }
155 
156 //==================================================================================================
157 void mergeKeys(
158     Reference< registry::XRegistryKey > const & xDest,
159     Reference< registry::XRegistryKey > const & xSource )
160     // throw( registry::InvalidRegistryException, registry::MergeConflictException, RuntimeException )
161 {
162     if (!xDest.is() || !xDest->isValid()) {
163         throw registry::InvalidRegistryException(
164             OUSTR("destination key is null or invalid!"),
165             Reference<XInterface>() );
166     }
167     if (xDest->isReadOnly())
168     {
169         throw registry::InvalidRegistryException(
170             OUString( RTL_CONSTASCII_USTRINGPARAM(
171                           "destination registry is read-only!  cannot merge!") ),
172             Reference< XInterface >() );
173     }
174 
175     t_links links;
176     links.reserve( 16 );
177     mergeKeys( xDest, xSource, links );
178 
179     for ( size_t nPos = links.size(); nPos--; )
180     {
181         Link const & r = links[ nPos ];
182         OSL_VERIFY( xDest->createLink( r.m_name, r.m_target ) );
183     }
184 }
185 
186 }
187