xref: /trunk/main/desktop/source/migration/migration.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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_desktop.hxx"
30 
31 #include <map>
32 #include <new>
33 #include <set>
34 
35 #include "migration.hxx"
36 #include "migration_impl.hxx"
37 #include "cfgfilter.hxx"
38 
39 #include <unotools/textsearch.hxx>
40 #include <comphelper/processfactory.hxx>
41 #include <comphelper/sequence.hxx>
42 #include <unotools/bootstrap.hxx>
43 #include <rtl/bootstrap.hxx>
44 #include <rtl/uri.hxx>
45 #include <tools/config.hxx>
46 #include <i18npool/lang.h>
47 #include <tools/urlobj.hxx>
48 #include <osl/file.hxx>
49 #include <osl/mutex.hxx>
50 #include <ucbhelper/content.hxx>
51 #include <osl/security.hxx>
52 #include <unotools/configmgr.hxx>
53 
54 #include <com/sun/star/configuration/Update.hpp>
55 #include <com/sun/star/lang/XInitialization.hpp>
56 #include <com/sun/star/task/XJob.hpp>
57 #include <com/sun/star/beans/NamedValue.hpp>
58 #include <com/sun/star/beans/XPropertySet.hpp>
59 #include <com/sun/star/util/XRefreshable.hpp>
60 #include <com/sun/star/util/XChangesBatch.hpp>
61 #include <com/sun/star/util/XStringSubstitution.hpp>
62 #include <com/sun/star/embed/ElementModes.hpp>
63 #include <com/sun/star/embed/XStorage.hpp>
64 #include <com/sun/star/ui/XUIConfiguration.hpp>
65 #include <com/sun/star/ui/XUIConfigurationStorage.hpp>
66 #include <com/sun/star/ui/XUIConfigurationPersistence.hpp>
67 
68 using namespace rtl;
69 using namespace osl;
70 using namespace std;
71 using namespace com::sun::star::task;
72 using namespace com::sun::star::lang;
73 using namespace com::sun::star::beans;
74 using namespace com::sun::star::util;
75 using namespace com::sun::star::container;
76 using com::sun::star::uno::Exception;
77 using namespace com::sun::star;
78 
79 namespace desktop {
80 
81 static const ::rtl::OUString ITEM_DESCRIPTOR_COMMANDURL = ::rtl::OUString::createFromAscii("CommandURL");
82 static const ::rtl::OUString ITEM_DESCRIPTOR_CONTAINER = ::rtl::OUString::createFromAscii("ItemDescriptorContainer");
83 static const ::rtl::OUString ITEM_DESCRIPTOR_LABEL = ::rtl::OUString::createFromAscii("Label");
84 
85 static const ::rtl::OUString MENU_SEPERATOR = ::rtl::OUString::createFromAscii(" | ");
86 static const ::rtl::OUString MENU_SUBMENU = ::rtl::OUString::createFromAscii("...");
87 
88 ::rtl::OUString retrieveLabelFromCommand(const ::rtl::OUString& sCommand, const ::rtl::OUString& sModuleIdentifier)
89 {
90     ::rtl::OUString sLabel;
91 
92     uno::Reference< container::XNameAccess > xUICommands;
93     uno::Reference< container::XNameAccess > xNameAccess( ::comphelper::getProcessServiceFactory()->createInstance( ::rtl::OUString::createFromAscii("com.sun.star.frame.UICommandDescription") ), uno::UNO_QUERY );
94     if ( xNameAccess.is() )
95     {
96         uno::Any a = xNameAccess->getByName( sModuleIdentifier );
97         a >>= xUICommands;
98     }
99     if (xUICommands.is())
100     {
101         if ( sCommand.getLength() > 0 )
102         {
103             rtl::OUString aStr;
104             ::uno::Sequence< beans::PropertyValue > aPropSeq;
105             try
106             {
107                 uno::Any a( xUICommands->getByName( sCommand ));
108                 if ( a >>= aPropSeq )
109                 {
110                     for ( sal_Int32 i = 0; i < aPropSeq.getLength(); i++ )
111                     {
112                         if ( aPropSeq[i].Name.equalsAscii( "Label" ))
113                         {
114                             aPropSeq[i].Value >>= aStr;
115                             break;
116                         }
117                     }
118                 }
119 
120                 sLabel = aStr;
121             }
122 
123             catch(container::NoSuchElementException&)
124             {
125                 sLabel = sCommand;
126                 sal_Int32 nIndex = sLabel.indexOf(':');
127                 if (nIndex>=0 && nIndex <= sLabel.getLength()-1)
128                     sLabel = sLabel.copy(nIndex+1);
129             }
130 
131         }
132     }
133 
134     return sLabel;
135 }
136 
137 ::rtl::OUString stripHotKey( const ::rtl::OUString& str )
138 {
139     sal_Int32 index = str.indexOf( '~' );
140     if ( index == -1 )
141     {
142         return str;
143     }
144     else
145     {
146         return str.replaceAt( index, 1, ::rtl::OUString() );
147     }
148 }
149 
150 ::rtl::OUString mapModuleShortNameToIdentifier(const ::rtl::OUString& sShortName)
151 {
152     ::rtl::OUString sIdentifier;
153 
154     if (sShortName.equals(::rtl::OUString::createFromAscii("StartModule")))
155         sIdentifier = ::rtl::OUString::createFromAscii("com.sun.star.frame.StartModule");
156 
157     else if (sShortName.equals(::rtl::OUString::createFromAscii("swriter")))
158         sIdentifier = ::rtl::OUString::createFromAscii("com.sun.star.text.TextDocument");
159 
160     else if (sShortName.equals(::rtl::OUString::createFromAscii("scalc")))
161         sIdentifier = ::rtl::OUString::createFromAscii("com.sun.star.sheet.SpreadsheetDocument");
162 
163     else if (sShortName.equals(::rtl::OUString::createFromAscii("sdraw")))
164         sIdentifier = ::rtl::OUString::createFromAscii("com.sun.star.drawing.DrawingDocument");
165 
166     else if (sShortName.equals(::rtl::OUString::createFromAscii("simpress")))
167         sIdentifier = ::rtl::OUString::createFromAscii("com.sun.star.presentation.PresentationDocument");
168 
169     else if (sShortName.equals(::rtl::OUString::createFromAscii("smath")))
170         sIdentifier = ::rtl::OUString::createFromAscii("com.sun.star.formula.FormulaProperties");
171 
172     else if (sShortName.equals(::rtl::OUString::createFromAscii("schart")))
173         sIdentifier = ::rtl::OUString::createFromAscii("com.sun.star.chart2.ChartDocument");
174 
175     else if (sShortName.equals(::rtl::OUString::createFromAscii("BasicIDE")))
176         sIdentifier = ::rtl::OUString::createFromAscii("com.sun.star.script.BasicIDE");
177 
178     else if (sShortName.equals(::rtl::OUString::createFromAscii("dbapp")))
179         sIdentifier = ::rtl::OUString::createFromAscii("com.sun.star.sdb.OfficeDatabaseDocument");
180 
181     else if (sShortName.equals(::rtl::OUString::createFromAscii("sglobal")))
182         sIdentifier = ::rtl::OUString::createFromAscii("com.sun.star.text.GlobalDocument");
183 
184     else if (sShortName.equals(::rtl::OUString::createFromAscii("sweb")))
185         sIdentifier = ::rtl::OUString::createFromAscii("com.sun.star.text.WebDocument");
186 
187     else if (sShortName.equals(::rtl::OUString::createFromAscii("swxform")))
188         sIdentifier = ::rtl::OUString::createFromAscii("com.sun.star.xforms.XMLFormDocument");
189 
190     else if (sShortName.equals(::rtl::OUString::createFromAscii("sbibliography")))
191         sIdentifier = ::rtl::OUString::createFromAscii("com.sun.star.frame.Bibliography");
192 
193     return sIdentifier;
194 }
195 
196 static MigrationImpl *pImpl = 0;
197 static Mutex aMutex;
198 static MigrationImpl *getImpl()
199 {
200     MutexGuard aGuard(aMutex);
201     if (pImpl == 0)
202         pImpl = new MigrationImpl(comphelper::getProcessServiceFactory());
203     return pImpl;
204 }
205 
206 static void releaseImpl()
207 {
208     MutexGuard aGuard(aMutex);
209     if (pImpl != 0)
210     {
211         delete pImpl;
212         pImpl = 0;
213     }
214 }
215 
216 // static main entry point for the migration process
217 void Migration::doMigration()
218 {
219     sal_Bool bResult = sal_False;
220     try {
221         bResult = getImpl()->doMigration();
222     } catch (Exception& e)
223     {
224         OString aMsg("doMigration() exception: ");
225         aMsg += OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US);
226         OSL_ENSURE(sal_False, aMsg.getStr());
227     }
228     OSL_ENSURE(bResult, "Migration has not been successfull");
229     // shut down migration framework
230     releaseImpl();
231 }
232 
233 void Migration::cancelMigration()
234 {
235     releaseImpl();
236 }
237 
238 sal_Bool Migration::checkMigration()
239 {
240     return getImpl()->checkMigration();
241 }
242 
243 OUString Migration::getOldVersionName()
244 {
245     return getImpl()->getOldVersionName();
246 }
247 
248 OUString MigrationImpl::getOldVersionName()
249 {
250     return m_aInfo.productname;
251 }
252 
253 sal_Bool MigrationImpl::checkMigration()
254 {
255     if (m_aInfo.userdata.getLength() > 0 && ! checkMigrationCompleted())
256         return sal_True;
257     else
258         return sal_False;
259 }
260 
261 MigrationImpl::MigrationImpl(const uno::Reference< XMultiServiceFactory >& xFactory)
262     : m_vrVersions(new strings_v)
263     , m_xFactory(xFactory)
264 {
265     readAvailableMigrations(m_vMigrationsAvailable);
266     sal_Int32 nIndex = findPreferedMigrationProcess(m_vMigrationsAvailable);
267     if ( nIndex >= 0 )
268         m_vrMigrations = readMigrationSteps(m_vMigrationsAvailable[nIndex].name);
269 }
270 
271 MigrationImpl::~MigrationImpl()
272 {
273 
274 }
275 
276 sal_Bool MigrationImpl::doMigration()
277 {
278     // compile file list for migration
279     m_vrFileList = compileFileList();
280 
281     sal_Bool result = sal_False;
282     try
283     {
284         NewVersionUIInfo aNewVersionUIInfo;
285         ::std::vector< MigrationModuleInfo > vModulesInfo = dectectUIChangesForAllModules();
286         aNewVersionUIInfo.init(vModulesInfo);
287 
288         copyFiles();
289 
290         const ::rtl::OUString sMenubarResourceURL = ::rtl::OUString::createFromAscii("private:resource/menubar/menubar");
291         const ::rtl::OUString sToolbarResourcePre = ::rtl::OUString::createFromAscii("private:resource/toolbar/");
292         for (sal_uInt32 i=0; i<vModulesInfo.size(); ++i)
293         {
294             ::rtl::OUString sModuleIdentifier = mapModuleShortNameToIdentifier(vModulesInfo[i].sModuleShortName);
295             if (sModuleIdentifier.getLength()==0)
296                 continue;
297 
298             uno::Sequence< uno::Any > lArgs(2);
299             ::rtl::OUString aOldCfgDataPath = m_aInfo.userdata + ::rtl::OUString::createFromAscii("/user/config/soffice.cfg/modules/");
300             lArgs[0] <<= aOldCfgDataPath + vModulesInfo[i].sModuleShortName;
301             lArgs[1] <<= embed::ElementModes::READ;
302 
303             uno::Reference< lang::XSingleServiceFactory > xStorageFactory(m_xFactory->createInstance(::rtl::OUString::createFromAscii("com.sun.star.embed.FileSystemStorageFactory")), uno::UNO_QUERY);
304             uno::Reference< embed::XStorage >             xModules;
305 
306             xModules = uno::Reference< embed::XStorage >(xStorageFactory->createInstanceWithArguments(lArgs), uno::UNO_QUERY);
307             uno::Reference< ui::XUIConfigurationManager > xOldCfgManager( m_xFactory->createInstance( rtl::OUString::createFromAscii("com.sun.star.ui.UIConfigurationManager")), uno::UNO_QUERY );
308             uno::Reference< ui::XUIConfigurationStorage > xOldCfgStorage( xOldCfgManager, uno::UNO_QUERY );
309             uno::Reference< ui::XUIConfigurationPersistence > xOldCfgPersistence( xOldCfgManager, uno::UNO_QUERY );
310 
311             if ( xOldCfgStorage.is() && xOldCfgPersistence.is() && xModules.is() )
312             {
313                     xOldCfgStorage->setStorage( xModules );
314                     xOldCfgPersistence->reload();
315             }
316 
317             uno::Reference< ui::XUIConfigurationManager > xCfgManager = aNewVersionUIInfo.getConfigManager(vModulesInfo[i].sModuleShortName);
318 
319             if (vModulesInfo[i].bHasMenubar)
320             {
321                 uno::Reference< container::XIndexContainer > xOldVersionMenuSettings = uno::Reference< container::XIndexContainer >(xOldCfgManager->getSettings(sMenubarResourceURL, sal_True), uno::UNO_QUERY);
322                 uno::Reference< container::XIndexContainer > xNewVersionMenuSettings = aNewVersionUIInfo.getNewMenubarSettings(vModulesInfo[i].sModuleShortName);
323                 ::rtl::OUString sParent;
324                 compareOldAndNewConfig(sParent, xOldVersionMenuSettings, xNewVersionMenuSettings, sMenubarResourceURL);
325                 mergeOldToNewVersion(xCfgManager, xNewVersionMenuSettings, sModuleIdentifier, sMenubarResourceURL);
326             }
327 
328             sal_Int32 nToolbars = vModulesInfo[i].m_vToolbars.size();
329             if (nToolbars >0)
330             {
331                 for (sal_Int32 j=0; j<nToolbars; ++j)
332                 {
333                     ::rtl::OUString sToolbarName = vModulesInfo[i].m_vToolbars[j];
334                     ::rtl::OUString sToolbarResourceURL = sToolbarResourcePre + sToolbarName;
335 
336                     uno::Reference< container::XIndexContainer > xOldVersionToolbarSettings = uno::Reference< container::XIndexContainer >(xOldCfgManager->getSettings(sToolbarResourceURL, sal_True), uno::UNO_QUERY);
337                     uno::Reference< container::XIndexContainer > xNewVersionToolbarSettings = aNewVersionUIInfo.getNewToolbarSettings(vModulesInfo[i].sModuleShortName, sToolbarName);
338                     ::rtl::OUString sParent;
339                     compareOldAndNewConfig(sParent, xOldVersionToolbarSettings, xNewVersionToolbarSettings, sToolbarResourceURL);
340                     mergeOldToNewVersion(xCfgManager, xNewVersionToolbarSettings, sModuleIdentifier, sToolbarResourceURL);
341                 }
342             }
343 
344             m_aOldVersionItemsHashMap.clear();
345             m_aNewVersionItemsHashMap.clear();
346         }
347 
348         // execute the migration items from Setup.xcu
349         copyConfig();
350 
351         // execute custom migration services from Setup.xcu
352         // and refresh the cache
353         runServices();
354         refresh();
355 
356         result = sal_True;
357     } catch (...)
358     {
359         OString aMsg("An unexpected exception was thrown during migration");
360         aMsg += "\nOldVersion: " + OUStringToOString(m_aInfo.productname, RTL_TEXTENCODING_ASCII_US);
361         aMsg += "\nDataPath  : " + OUStringToOString(m_aInfo.userdata, RTL_TEXTENCODING_ASCII_US);
362         OSL_ENSURE(sal_False, aMsg.getStr());
363     }
364 
365     // prevent running the migration multiple times
366     setMigrationCompleted();
367     return result;
368 }
369 
370 void MigrationImpl::refresh()
371 {
372     uno::Reference< XRefreshable > xRefresh(m_xFactory->createInstance(
373                 OUString::createFromAscii("com.sun.star.configuration.ConfigurationProvider")), uno::UNO_QUERY);
374     if (xRefresh.is())
375         xRefresh->refresh();
376     else
377         OSL_ENSURE(sal_False, "could not get XRefresh interface from default config provider. No refresh done.");
378 
379 }
380 
381 void MigrationImpl::setMigrationCompleted()
382 {
383     try {
384         uno::Reference< XPropertySet > aPropertySet(getConfigAccess("org.openoffice.Setup/Office", true), uno::UNO_QUERY_THROW);
385         aPropertySet->setPropertyValue(OUString::createFromAscii("MigrationCompleted"), uno::makeAny(sal_True));
386         uno::Reference< XChangesBatch >(aPropertySet, uno::UNO_QUERY_THROW)->commitChanges();
387     } catch (...) {
388         // fail silently
389     }
390 }
391 
392 sal_Bool MigrationImpl::checkMigrationCompleted()
393 {
394     sal_Bool bMigrationCompleted = sal_False;
395     try {
396         uno::Reference< XPropertySet > aPropertySet(
397             getConfigAccess("org.openoffice.Setup/Office"), uno::UNO_QUERY_THROW);
398         aPropertySet->getPropertyValue(
399             OUString::createFromAscii("MigrationCompleted")) >>= bMigrationCompleted;
400     } catch (Exception&) {
401         // just return false...
402     }
403     return bMigrationCompleted;
404 }
405 
406 static void insertSorted(migrations_available& rAvailableMigrations, supported_migration& aSupportedMigration)
407 {
408     bool                           bInserted( false );
409     migrations_available::iterator pIter = rAvailableMigrations.begin();
410     while ( !bInserted && pIter != rAvailableMigrations.end())
411     {
412         if ( pIter->nPriority < aSupportedMigration.nPriority )
413         {
414             rAvailableMigrations.insert(pIter, aSupportedMigration );
415             bInserted = true;
416             break; // i111193: insert invalidates iterator!
417         }
418         ++pIter;
419     }
420     if ( !bInserted )
421         rAvailableMigrations.push_back( aSupportedMigration );
422 }
423 
424 bool MigrationImpl::readAvailableMigrations(migrations_available& rAvailableMigrations)
425 {
426     // get supported version names
427     uno::Reference< XNameAccess > aMigrationAccess(getConfigAccess("org.openoffice.Setup/Migration/SupportedVersions"), uno::UNO_QUERY_THROW);
428     uno::Sequence< OUString > seqSupportedVersions = aMigrationAccess->getElementNames();
429 
430     const OUString aVersionIdentifiers( RTL_CONSTASCII_USTRINGPARAM( "VersionIdentifiers" ));
431     const OUString aPriorityIdentifier( RTL_CONSTASCII_USTRINGPARAM( "Priority" ));
432 
433     for (sal_Int32 i=0; i<seqSupportedVersions.getLength(); i++)
434     {
435         sal_Int32                 nPriority( 0 );
436         uno::Sequence< OUString > seqVersions;
437         uno::Reference< XNameAccess > xMigrationData( aMigrationAccess->getByName(seqSupportedVersions[i]), uno::UNO_QUERY_THROW );
438         xMigrationData->getByName( aVersionIdentifiers ) >>= seqVersions;
439         xMigrationData->getByName( aPriorityIdentifier ) >>= nPriority;
440 
441         supported_migration aSupportedMigration;
442         aSupportedMigration.name      = seqSupportedVersions[i];
443         aSupportedMigration.nPriority = nPriority;
444         for (sal_Int32 j=0; j<seqVersions.getLength(); j++)
445             aSupportedMigration.supported_versions.push_back(seqVersions[j].trim());
446         insertSorted( rAvailableMigrations, aSupportedMigration );
447     }
448 
449     return true;
450 }
451 
452 migrations_vr MigrationImpl::readMigrationSteps(const ::rtl::OUString& rMigrationName)
453 {
454     // get migration access
455     uno::Reference< XNameAccess > aMigrationAccess(getConfigAccess("org.openoffice.Setup/Migration/SupportedVersions"), uno::UNO_QUERY_THROW);
456     uno::Reference< XNameAccess > xMigrationData( aMigrationAccess->getByName(rMigrationName), uno::UNO_QUERY_THROW );
457 
458     // get migration description from from org.openoffice.Setup/Migration
459     // and build vector of migration steps
460     OUString aMigrationSteps( RTL_CONSTASCII_USTRINGPARAM( "MigrationSteps" ));
461     uno::Reference< XNameAccess > theNameAccess(xMigrationData->getByName(aMigrationSteps), uno::UNO_QUERY_THROW);
462     uno::Sequence< OUString > seqMigrations = theNameAccess->getElementNames();
463     uno::Reference< XNameAccess > tmpAccess;
464     uno::Reference< XNameAccess > tmpAccess2;
465     uno::Sequence< OUString > tmpSeq;
466     migrations_vr vrMigrations(new migrations_v);
467     for (sal_Int32 i = 0; i < seqMigrations.getLength(); i++)
468     {
469         // get current migration step
470         theNameAccess->getByName(seqMigrations[i]) >>= tmpAccess;
471         // tmpStepPtr = new migration_step();
472         migration_step tmpStep;
473         tmpStep.name = seqMigrations[i];
474 
475         // read included files from current step description
476         ::rtl::OUString aSeqEntry;
477         if (tmpAccess->getByName(OUString::createFromAscii("IncludedFiles")) >>= tmpSeq)
478         {
479             for (sal_Int32 j=0; j<tmpSeq.getLength(); j++)
480             {
481                 aSeqEntry = tmpSeq[j];
482                 tmpStep.includeFiles.push_back(aSeqEntry);
483             }
484         }
485 
486         // exluded files...
487         if (tmpAccess->getByName(OUString::createFromAscii("ExcludedFiles")) >>= tmpSeq)
488         {
489             for (sal_Int32 j=0; j<tmpSeq.getLength(); j++)
490                 tmpStep.excludeFiles.push_back(tmpSeq[j]);
491         }
492 
493         // included nodes...
494         if (tmpAccess->getByName(OUString::createFromAscii("IncludedNodes")) >>= tmpSeq)
495         {
496             for (sal_Int32 j=0; j<tmpSeq.getLength(); j++)
497                 tmpStep.includeConfig.push_back(tmpSeq[j]);
498         }
499 
500         // excluded nodes...
501         if (tmpAccess->getByName(OUString::createFromAscii("ExcludedNodes")) >>= tmpSeq)
502         {
503             for (sal_Int32 j=0; j<tmpSeq.getLength(); j++)
504                 tmpStep.excludeConfig.push_back(tmpSeq[j]);
505         }
506 
507         // included extensions...
508         if (tmpAccess->getByName(OUString::createFromAscii("IncludedExtensions")) >>= tmpSeq)
509         {
510             for (sal_Int32 j=0; j<tmpSeq.getLength(); j++)
511                 tmpStep.includeExtensions.push_back(tmpSeq[j]);
512         }
513 
514         // excluded extensions...
515         if (tmpAccess->getByName(OUString::createFromAscii("ExcludedExtensions")) >>= tmpSeq)
516         {
517             for (sal_Int32 j=0; j<tmpSeq.getLength(); j++)
518             {
519                 aSeqEntry = tmpSeq[j];
520                 tmpStep.excludeExtensions.push_back(aSeqEntry);
521             }
522         }
523 
524         // generic service
525         tmpAccess->getByName(OUString::createFromAscii("MigrationService")) >>= tmpStep.service;
526 
527         vrMigrations->push_back(tmpStep);
528     }
529     return vrMigrations;
530 }
531 
532 static FileBase::RC _checkAndCreateDirectory(INetURLObject& dirURL)
533 {
534     FileBase::RC result = Directory::create(dirURL.GetMainURL(INetURLObject::DECODE_TO_IURI));
535     if (result == FileBase::E_NOENT)
536     {
537         INetURLObject baseURL(dirURL);
538         baseURL.removeSegment();
539         _checkAndCreateDirectory(baseURL);
540         return Directory::create(dirURL.GetMainURL(INetURLObject::DECODE_TO_IURI));
541     } else
542         return result;
543 }
544 
545 install_info MigrationImpl::findInstallation(const strings_v& rVersions)
546 {
547     rtl::OUString aProductName;
548     uno::Any aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTNAME );
549     aRet >>= aProductName;
550     aProductName = aProductName.toAsciiLowerCase();
551 
552     install_info aInfo;
553     strings_v::const_iterator i_ver = rVersions.begin();
554     uno::Reference < util::XStringSubstitution > xSubst( ::comphelper::getProcessServiceFactory()->createInstance(::rtl::OUString::createFromAscii("com.sun.star.util.PathSubstitution")), uno::UNO_QUERY );
555     while (i_ver != rVersions.end())
556     {
557         ::rtl::OUString aVersion, aProfileName;
558         sal_Int32 nSeparatorIndex = (*i_ver).indexOf('=');
559         if ( nSeparatorIndex != -1 )
560         {
561             aVersion = (*i_ver).copy( 0, nSeparatorIndex );
562             aProfileName = (*i_ver).copy( nSeparatorIndex+1 );
563         }
564 
565         if ( aVersion.getLength() && aProfileName.getLength() &&
566                 ( !aInfo.userdata.getLength() || !aProfileName.toAsciiLowerCase().compareTo( aProductName, aProductName.getLength() ) )
567            )
568         {
569             ::rtl::OUString aUserInst;
570             osl::Security().getConfigDir( aUserInst );
571             if ( aUserInst.getLength() && aUserInst[ aUserInst.getLength()-1 ] != '/' )
572                 aUserInst += ::rtl::OUString::createFromAscii("/");
573 #if defined UNX && ! defined MACOSX
574             // tribute to whoever had the "great" idea to use different names on Windows and Unix
575             aUserInst += ::rtl::OUString::createFromAscii(".");
576 #endif
577             aUserInst += aProfileName;
578             try
579             {
580                 INetURLObject aObj(aUserInst);
581                 ::ucbhelper::Content aCnt( aObj.GetMainURL( INetURLObject::NO_DECODE ), uno::Reference< ucb::XCommandEnvironment > () );
582                 aCnt.isDocument();
583                 aInfo.userdata = aObj.GetMainURL( INetURLObject::NO_DECODE );
584                 aInfo.productname = aVersion;
585             }
586             catch( uno::Exception& ){}
587         }
588         ++i_ver;
589     }
590 
591     return aInfo;
592 }
593 
594 sal_Int32 MigrationImpl::findPreferedMigrationProcess(const migrations_available& rAvailableMigrations)
595 {
596     sal_Int32    nIndex( -1 );
597     sal_Int32    i( 0 );
598 
599     migrations_available::const_iterator rIter = rAvailableMigrations.begin();
600     while ( rIter != rAvailableMigrations.end() )
601     {
602         install_info aInstallInfo = findInstallation(rIter->supported_versions);
603         if (aInstallInfo.productname.getLength() > 0 )
604         {
605             m_aInfo = aInstallInfo;
606             nIndex  = i;
607             break;
608         }
609         ++i;
610         ++rIter;
611     }
612 
613     return nIndex;
614 }
615 
616 strings_vr MigrationImpl::applyPatterns(const strings_v& vSet, const strings_v& vPatterns) const
617 {
618     using namespace utl;
619     strings_vr vrResult(new strings_v);
620     strings_v::const_iterator i_set;
621     strings_v::const_iterator i_pat = vPatterns.begin();
622     while (i_pat != vPatterns.end())
623     {
624         // find matches for this pattern in input set
625         // and copy them to the result
626         SearchParam param(*i_pat, SearchParam::SRCH_REGEXP);
627         TextSearch ts(param, LANGUAGE_DONTKNOW);
628         i_set = vSet.begin();
629         xub_StrLen start = 0;
630         xub_StrLen end = 0;
631         while (i_set != vSet.end())
632         {
633             end = (xub_StrLen)(i_set->getLength());
634             if (ts.SearchFrwrd(*i_set, &start, &end))
635                 vrResult->push_back(*i_set);
636             i_set++;
637         }
638         i_pat++;
639     }
640     return vrResult;
641 }
642 
643 strings_vr MigrationImpl::getAllFiles(const OUString& baseURL) const
644 {
645     using namespace osl;
646     strings_vr vrResult(new strings_v);
647 
648     // get sub dirs
649     Directory dir(baseURL);
650     if (dir.open() == FileBase::E_None)
651     {
652         strings_v vSubDirs;
653         strings_vr vrSubResult;
654 
655         // work through directory contents...
656         DirectoryItem item;
657         FileStatus fs(FileStatusMask_Type | FileStatusMask_FileURL);
658         while (dir.getNextItem(item) == FileBase::E_None)
659         {
660             if (item.getFileStatus(fs) == FileBase::E_None)
661             {
662                 if (fs.getFileType() == FileStatus::Directory)
663                     vSubDirs.push_back(fs.getFileURL());
664                 else
665                     vrResult->push_back(fs.getFileURL());
666             }
667         }
668 
669         // recurse subfolders
670         strings_v::const_iterator i = vSubDirs.begin();
671         while (i != vSubDirs.end())
672         {
673             vrSubResult = getAllFiles(*i);
674             vrResult->insert(vrResult->end(), vrSubResult->begin(), vrSubResult->end());
675             i++;
676         }
677     }
678     return vrResult;
679 }
680 
681 strings_vr MigrationImpl::compileFileList()
682 {
683 
684     strings_vr vrResult(new strings_v);
685     strings_vr vrInclude;
686     strings_vr vrExclude;
687     strings_vr vrTemp;
688 
689 #ifdef SAL_OS2
690     if (m_aInfo.userdata.getLength() == 0)
691         return vrResult;
692 #endif
693 
694     // get a list of all files:
695     strings_vr vrFiles = getAllFiles(m_aInfo.userdata);
696 
697     // get a file list result for each migration step
698     migrations_v::const_iterator i_migr = m_vrMigrations->begin();
699     while (i_migr != m_vrMigrations->end())
700     {
701         vrInclude = applyPatterns(*vrFiles, i_migr->includeFiles);
702         vrExclude = applyPatterns(*vrFiles, i_migr->excludeFiles);
703         substract(*vrInclude, *vrExclude);
704         vrResult->insert(vrResult->end(), vrInclude->begin(), vrInclude->end());
705         i_migr++;
706     }
707     return vrResult;
708 }
709 
710 namespace {
711 
712 struct componentParts {
713     std::set< rtl::OUString > includedPaths;
714     std::set< rtl::OUString > excludedPaths;
715 };
716 
717 typedef std::map< rtl::OUString, componentParts > Components;
718 
719 bool getComponent(rtl::OUString const & path, rtl::OUString * component) {
720     OSL_ASSERT(component != 0);
721     if (path.getLength() == 0 || path[0] != '/') {
722         OSL_TRACE(
723             ("configuration migration in/exclude path %s ignored (does not"
724              " start with slash)"),
725             rtl::OUStringToOString(path, RTL_TEXTENCODING_UTF8).getStr());
726         return false;
727     }
728     sal_Int32 i = path.indexOf('/', 1);
729     *component = i < 0 ? path.copy(1) : path.copy(1, i - 1);
730     return true;
731 }
732 
733 uno::Sequence< rtl::OUString > setToSeq(std::set< rtl::OUString > const & set) {
734     std::set< rtl::OUString >::size_type n = set.size();
735     if (n > SAL_MAX_INT32) {
736         throw std::bad_alloc();
737     }
738     uno::Sequence< rtl::OUString > seq(static_cast< sal_Int32 >(n));
739     sal_Int32 i = 0;
740     for (std::set< rtl::OUString >::const_iterator j(set.begin());
741          j != set.end(); ++j)
742     {
743         seq[i++] = *j;
744     }
745     return seq;
746 }
747 
748 }
749 
750 void MigrationImpl::copyConfig() {
751     Components comps;
752     for (migrations_v::const_iterator i(m_vrMigrations->begin());
753          i != m_vrMigrations->end(); ++i)
754     {
755         for (strings_v::const_iterator j(i->includeConfig.begin());
756              j != i->includeConfig.end(); ++j)
757         {
758             rtl::OUString comp;
759             if (getComponent(*j, &comp)) {
760                 comps[comp].includedPaths.insert(*j);
761             }
762         }
763         for (strings_v::const_iterator j(i->excludeConfig.begin());
764              j != i->excludeConfig.end(); ++j)
765         {
766             rtl::OUString comp;
767             if (getComponent(*j, &comp)) {
768                 comps[comp].excludedPaths.insert(*j);
769             }
770         }
771     }
772     for (Components::const_iterator i(comps.begin()); i != comps.end(); ++i) {
773         if (!i->second.includedPaths.empty()) {
774             rtl::OUStringBuffer buf(m_aInfo.userdata);
775             buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("/user/registry/data"));
776             sal_Int32 n = 0;
777             do {
778                 rtl::OUString seg(i->first.getToken(0, '.', n));
779                 rtl::OUString enc(
780                     rtl::Uri::encode(
781                         seg, rtl_UriCharClassPchar, rtl_UriEncodeStrict,
782                         RTL_TEXTENCODING_UTF8));
783                 if (enc.getLength() == 0 && seg.getLength() != 0) {
784                     OSL_TRACE(
785                         ("configuration migration component %s ignored (cannot"
786                          " be encoded as file path)"),
787                         rtl::OUStringToOString(
788                             i->first, RTL_TEXTENCODING_UTF8).getStr());
789                     goto next;
790                 }
791                 buf.append(sal_Unicode('/'));
792                 buf.append(enc);
793             } while (n >= 0);
794             buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(".xcu"));
795             configuration::Update::get(
796                 comphelper::getProcessComponentContext())->
797                 insertModificationXcuFile(
798                     buf.makeStringAndClear(), setToSeq(i->second.includedPaths),
799                     setToSeq(i->second.excludedPaths));
800         } else {
801             OSL_TRACE(
802                 ("configuration migration component %s ignored (only excludes,"
803                  " no includes)"),
804                 rtl::OUStringToOString(
805                     i->first, RTL_TEXTENCODING_UTF8).getStr());
806         }
807     next:;
808     }
809 }
810 
811 // removes elements of vector 2 in vector 1
812 void MigrationImpl::substract(strings_v& va, const strings_v& vb_c) const
813 {
814     strings_v vb(vb_c);
815     // ensure uniqueness of entries
816     sort(va.begin(), va.end());
817     sort(vb.begin(), vb.end());
818     unique(va.begin(), va.end());
819     unique(vb.begin(), vb.end());
820 
821     strings_v::const_iterator i_ex = vb.begin();
822     strings_v::iterator i_in;
823     strings_v::iterator i_next;
824     while (i_ex != vb.end())
825     {
826         i_in = va.begin();
827         while (i_in != va.end())
828         {
829             if ( *i_in == *i_ex)
830             {
831                 i_next = i_in+1;
832                 va.erase(i_in);
833                 i_in = i_next;
834                 // we can only find one match since we
835                 // ensured uniquness of the entries. ergo:
836                 break;
837             }
838             else
839                 i_in++;
840         }
841         i_ex++;
842     }
843 }
844 
845 uno::Reference< XNameAccess > MigrationImpl::getConfigAccess(const sal_Char* pPath, sal_Bool bUpdate)
846 {
847     uno::Reference< XNameAccess > xNameAccess;
848     try{
849         OUString sConfigSrvc = OUString::createFromAscii("com.sun.star.configuration.ConfigurationProvider");
850         OUString sAccessSrvc;
851         if (bUpdate)
852             sAccessSrvc = OUString::createFromAscii("com.sun.star.configuration.ConfigurationUpdateAccess");
853         else
854             sAccessSrvc = OUString::createFromAscii("com.sun.star.configuration.ConfigurationAccess");
855 
856         OUString sConfigURL = OUString::createFromAscii(pPath);
857 
858         // get configuration provider
859         uno::Reference< XMultiServiceFactory > theMSF = comphelper::getProcessServiceFactory();
860         uno::Reference< XMultiServiceFactory > theConfigProvider = uno::Reference< XMultiServiceFactory > (
861                 theMSF->createInstance( sConfigSrvc ),uno::UNO_QUERY_THROW );
862 
863         // access the provider
864         uno::Sequence< uno::Any > theArgs(1);
865         theArgs[ 0 ] <<= sConfigURL;
866         xNameAccess = uno::Reference< XNameAccess > (
867                 theConfigProvider->createInstanceWithArguments(
868                 sAccessSrvc, theArgs ), uno::UNO_QUERY_THROW );
869     } catch (com::sun::star::uno::Exception& e)
870     {
871         OString aMsg = OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US);
872         OSL_ENSURE(sal_False, aMsg.getStr());
873     }
874     return xNameAccess;
875 }
876 
877 void MigrationImpl::copyFiles()
878 {
879     strings_v::const_iterator i_file = m_vrFileList->begin();
880     OUString localName;
881     OUString destName;
882     OUString userInstall;
883     utl::Bootstrap::PathStatus aStatus;
884     aStatus = utl::Bootstrap::locateUserInstallation(userInstall);
885     if (aStatus == utl::Bootstrap::PATH_EXISTS)
886     {
887         while (i_file != m_vrFileList->end())
888         {
889 
890             // remove installation prefix from file
891             localName = i_file->copy(m_aInfo.userdata.getLength());
892             destName = userInstall + localName;
893             INetURLObject aURL(destName);
894             // check whether destination directory exists
895             aURL.removeSegment();
896             _checkAndCreateDirectory(aURL);
897             FileBase::RC copyResult = File::copy(*i_file, destName);
898             if (copyResult != FileBase::E_None)
899             {
900                 OString msg("Cannot copy ");
901                 msg += OUStringToOString(*i_file, RTL_TEXTENCODING_UTF8) + " to "
902                     +  OUStringToOString(destName, RTL_TEXTENCODING_UTF8);
903                 OSL_ENSURE(sal_False, msg.getStr());
904             }
905             i_file++;
906         }
907     }
908     else
909     {
910         OSL_ENSURE(sal_False, "copyFiles: UserInstall does not exist");
911     }
912 }
913 
914 void MigrationImpl::runServices()
915 {
916     // Build argument array
917     uno::Sequence< uno::Any > seqArguments(3);
918     seqArguments[0] = uno::makeAny(NamedValue(
919         OUString::createFromAscii("Productname"),
920         uno::makeAny(m_aInfo.productname)));
921     seqArguments[1] = uno::makeAny(NamedValue(
922         OUString::createFromAscii("UserData"),
923         uno::makeAny(m_aInfo.userdata)));
924 
925 
926     // create an instance of every migration service
927     // and execute the migration job
928     uno::Reference< XJob > xMigrationJob;
929 
930     migrations_v::const_iterator i_mig  = m_vrMigrations->begin();
931     while (i_mig != m_vrMigrations->end())
932     {
933         if( i_mig->service.getLength() > 0)
934         {
935 
936             try
937             {
938                 // set black list for extension migration
939                 uno::Sequence< rtl::OUString > seqExtBlackList;
940                 sal_uInt32 nSize = i_mig->excludeExtensions.size();
941                 if ( nSize > 0 )
942                     seqExtBlackList = comphelper::arrayToSequence< ::rtl::OUString >(
943                         &i_mig->excludeExtensions[0], nSize );
944                 seqArguments[2] = uno::makeAny(NamedValue(
945                     OUString::createFromAscii("ExtensionBlackList"),
946                     uno::makeAny( seqExtBlackList )));
947 
948                 xMigrationJob = uno::Reference< XJob >(m_xFactory->createInstanceWithArguments(
949                     i_mig->service, seqArguments), uno::UNO_QUERY_THROW);
950 
951                 xMigrationJob->execute(uno::Sequence< NamedValue >());
952 
953 
954             } catch (Exception& e)
955             {
956                 OString aMsg("Execution of migration service failed (Exception caught).\nService: ");
957                 aMsg += OUStringToOString(i_mig->service, RTL_TEXTENCODING_ASCII_US) + "\nMessage: ";
958                 aMsg += OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US);
959                 OSL_ENSURE(sal_False, aMsg.getStr());
960             } catch (...)
961             {
962                 OString aMsg("Execution of migration service failed (Exception caught).\nService: ");
963                 aMsg += OUStringToOString(i_mig->service, RTL_TEXTENCODING_ASCII_US) +
964                     "\nNo message available";
965                 OSL_ENSURE(sal_False, aMsg.getStr());
966             }
967 
968         }
969         i_mig++;
970     }
971 }
972 
973 ::std::vector< MigrationModuleInfo > MigrationImpl::dectectUIChangesForAllModules() const
974 {
975     ::std::vector< MigrationModuleInfo > vModulesInfo;
976     const ::rtl::OUString MENUBAR = ::rtl::OUString::createFromAscii("menubar");
977     const ::rtl::OUString TOOLBAR = ::rtl::OUString::createFromAscii("toolbar");
978 
979     uno::Sequence< uno::Any > lArgs(2);
980     lArgs[0] <<= m_aInfo.userdata + ::rtl::OUString::createFromAscii("/user/config/soffice.cfg/modules");
981     lArgs[1] <<= embed::ElementModes::READ;
982 
983     uno::Reference< lang::XSingleServiceFactory > xStorageFactory(m_xFactory->createInstance(::rtl::OUString::createFromAscii("com.sun.star.embed.FileSystemStorageFactory")), uno::UNO_QUERY);
984     uno::Reference< embed::XStorage >             xModules;
985 
986     xModules = uno::Reference< embed::XStorage >(xStorageFactory->createInstanceWithArguments(lArgs), uno::UNO_QUERY);
987     if (!xModules.is())
988         return vModulesInfo;
989 
990     uno::Reference< container::XNameAccess > xAccess = uno::Reference< container::XNameAccess >(xModules, uno::UNO_QUERY);
991     uno::Sequence< ::rtl::OUString > lNames = xAccess->getElementNames();
992     sal_Int32 nLength = lNames.getLength();
993     for (sal_Int32 i=0; i<nLength; ++i)
994     {
995         ::rtl::OUString sModuleShortName = lNames[i];
996         uno::Reference< embed::XStorage > xModule = xModules->openStorageElement(sModuleShortName, embed::ElementModes::READ);
997         if (xModule.is())
998         {
999             MigrationModuleInfo aModuleInfo;
1000 
1001             uno::Reference< embed::XStorage > xMenubar = xModule->openStorageElement(MENUBAR, embed::ElementModes::READ);
1002             if (xMenubar.is())
1003             {
1004                 uno::Reference< container::XNameAccess > xNameAccess = uno::Reference< container::XNameAccess >(xMenubar, uno::UNO_QUERY);
1005                 if (xNameAccess->getElementNames().getLength() > 0)
1006                 {
1007                     aModuleInfo.sModuleShortName = sModuleShortName;
1008                     aModuleInfo.bHasMenubar = sal_True;
1009                 }
1010             }
1011 
1012             uno::Reference< embed::XStorage > xToolbar = xModule->openStorageElement(TOOLBAR, embed::ElementModes::READ);
1013             if (xToolbar.is())
1014             {
1015                 const ::rtl::OUString RESOURCEURL_CUSTOM_ELEMENT = ::rtl::OUString::createFromAscii("custom_");
1016                 sal_Int32 nCustomLen = 7;
1017 
1018                 uno::Reference< container::XNameAccess > xNameAccess = uno::Reference< container::XNameAccess >(xToolbar, uno::UNO_QUERY);
1019                 ::uno::Sequence< ::rtl::OUString > lToolbars = xNameAccess->getElementNames();
1020                 for (sal_Int32 j=0; j<lToolbars.getLength(); ++j)
1021                 {
1022                     ::rtl::OUString sToolbarName = lToolbars[j];
1023                     if (sToolbarName.getLength()>=nCustomLen &&
1024                         sToolbarName.copy(0, nCustomLen).equals(RESOURCEURL_CUSTOM_ELEMENT))
1025                         continue;
1026 
1027                     aModuleInfo.sModuleShortName = sModuleShortName;
1028                     sal_Int32 nIndex = sToolbarName.lastIndexOf('.');
1029                     if (nIndex > 0)
1030                     {
1031                         ::rtl::OUString sExtension(sToolbarName.copy(nIndex));
1032                         ::rtl::OUString sToolbarResourceName(sToolbarName.copy(0, nIndex));
1033                         if (sToolbarResourceName.getLength()>0 && sExtension.equalsAsciiL(".xml", 4))
1034                             aModuleInfo.m_vToolbars.push_back(sToolbarResourceName);
1035                     }
1036                 }
1037             }
1038 
1039             if (aModuleInfo.sModuleShortName.getLength()>0)
1040                 vModulesInfo.push_back(aModuleInfo);
1041         }
1042     }
1043 
1044     return vModulesInfo;
1045 }
1046 
1047 void MigrationImpl::compareOldAndNewConfig(const ::rtl::OUString& sParent,
1048                                            const uno::Reference< container::XIndexContainer >& xIndexOld,
1049                                            const uno::Reference< container::XIndexContainer >& xIndexNew,
1050                                            const ::rtl::OUString& sResourceURL)
1051 {
1052     ::std::vector< MigrationItem > vOldItems;
1053     ::std::vector< MigrationItem > vNewItems;
1054     uno::Sequence< beans::PropertyValue > aProp;
1055     sal_Int32 nOldCount = xIndexOld->getCount();
1056     sal_Int32 nNewCount = xIndexNew->getCount();
1057 
1058     for (int n=0; n<nOldCount; ++n)
1059     {
1060         MigrationItem aMigrationItem;
1061         if (xIndexOld->getByIndex(n) >>= aProp)
1062         {
1063             for(int i=0; i<aProp.getLength(); ++i)
1064             {
1065                 if (aProp[i].Name.equals(ITEM_DESCRIPTOR_COMMANDURL))
1066                     aProp[i].Value >>= aMigrationItem.m_sCommandURL;
1067                 else if (aProp[i].Name.equals(ITEM_DESCRIPTOR_CONTAINER))
1068                     aProp[i].Value >>= aMigrationItem.m_xPopupMenu;
1069             }
1070 
1071             if (aMigrationItem.m_sCommandURL.getLength())
1072                 vOldItems.push_back(aMigrationItem);
1073         }
1074     }
1075 
1076     for (int n=0; n<nNewCount; ++n)
1077     {
1078         MigrationItem aMigrationItem;
1079         if (xIndexNew->getByIndex(n) >>= aProp)
1080         {
1081             for(int i=0; i<aProp.getLength(); ++i)
1082             {
1083                 if (aProp[i].Name.equals(ITEM_DESCRIPTOR_COMMANDURL))
1084                     aProp[i].Value >>= aMigrationItem.m_sCommandURL;
1085                 else if (aProp[i].Name.equals(ITEM_DESCRIPTOR_CONTAINER))
1086                     aProp[i].Value >>= aMigrationItem.m_xPopupMenu;
1087             }
1088 
1089             if (aMigrationItem.m_sCommandURL.getLength())
1090                 vNewItems.push_back(aMigrationItem);
1091         }
1092     }
1093 
1094     ::std::vector< MigrationItem >::iterator it;
1095 
1096     ::rtl::OUString sSibling;
1097     for (it = vOldItems.begin(); it!=vOldItems.end(); ++it)
1098     {
1099         ::std::vector< MigrationItem >::iterator pFound = ::std::find(vNewItems.begin(), vNewItems.end(), *it);
1100         if (pFound != vNewItems.end() && it->m_xPopupMenu.is())
1101         {
1102             ::rtl::OUString sName;
1103             if (sParent.getLength()>0)
1104                 sName = sParent + MENU_SEPERATOR + it->m_sCommandURL;
1105             else
1106                 sName = it->m_sCommandURL;
1107             compareOldAndNewConfig(sName, it->m_xPopupMenu, pFound->m_xPopupMenu, sResourceURL);
1108         }
1109         else if (pFound == vNewItems.end())
1110         {
1111             MigrationItem aMigrationItem(sParent, sSibling, it->m_sCommandURL, it->m_xPopupMenu);
1112             if (m_aOldVersionItemsHashMap.find(sResourceURL)==m_aOldVersionItemsHashMap.end())
1113             {
1114                 ::std::vector< MigrationItem > vMigrationItems;
1115                 m_aOldVersionItemsHashMap.insert(MigrationHashMap::value_type(sResourceURL, vMigrationItems));
1116                 m_aOldVersionItemsHashMap[sResourceURL].push_back(aMigrationItem);
1117             }
1118             else
1119             {
1120                 if (::std::find(m_aOldVersionItemsHashMap[sResourceURL].begin(), m_aOldVersionItemsHashMap[sResourceURL].end(), aMigrationItem)==m_aOldVersionItemsHashMap[sResourceURL].end())
1121                     m_aOldVersionItemsHashMap[sResourceURL].push_back(aMigrationItem);
1122             }
1123         }
1124 
1125         sSibling = it->m_sCommandURL;
1126     }
1127 
1128     ::rtl::OUString sNewSibling;
1129     uno::Reference< container::XIndexContainer > xPopup;
1130     for (it = vNewItems.begin(); it!=vNewItems.end(); ++it)
1131     {
1132         ::std::vector< MigrationItem >::iterator pFound = ::std::find(vOldItems.begin(), vOldItems.end(), *it);
1133         if (pFound != vOldItems.end() && it->m_xPopupMenu.is())
1134         {
1135             ::rtl::OUString sName;
1136             if (sParent.getLength()>0)
1137                 sName = sParent + MENU_SEPERATOR + it->m_sCommandURL;
1138             else
1139                 sName = it->m_sCommandURL;
1140             compareOldAndNewConfig(sName, pFound->m_xPopupMenu, it->m_xPopupMenu, sResourceURL);
1141         }
1142         else if (::std::find(vOldItems.begin(), vOldItems.end(), *it) == vOldItems.end())
1143         {
1144             MigrationItem aMigrationItem(sParent, sSibling, it->m_sCommandURL, it->m_xPopupMenu);
1145             if (m_aNewVersionItemsHashMap.find(sResourceURL)==m_aNewVersionItemsHashMap.end())
1146             {
1147                 ::std::vector< MigrationItem > vMigrationItems;
1148                 m_aNewVersionItemsHashMap.insert(MigrationHashMap::value_type(sResourceURL, vMigrationItems));
1149                 m_aNewVersionItemsHashMap[sResourceURL].push_back(aMigrationItem);
1150             }
1151             else
1152             {
1153                 if (::std::find(m_aNewVersionItemsHashMap[sResourceURL].begin(), m_aNewVersionItemsHashMap[sResourceURL].end(), aMigrationItem)==m_aNewVersionItemsHashMap[sResourceURL].end())
1154                     m_aNewVersionItemsHashMap[sResourceURL].push_back(aMigrationItem);
1155             }
1156         }
1157     }
1158 }
1159 
1160 void MigrationImpl::mergeOldToNewVersion(const uno::Reference< ui::XUIConfigurationManager >& xCfgManager,
1161                                          const uno::Reference< container::XIndexContainer>& xIndexContainer,
1162                                          const ::rtl::OUString& sModuleIdentifier,
1163                                          const ::rtl::OUString& sResourceURL)
1164 {
1165     MigrationHashMap::iterator pFound = m_aOldVersionItemsHashMap.find(sResourceURL);
1166     if (pFound==m_aOldVersionItemsHashMap.end())
1167         return;
1168 
1169     ::std::vector< MigrationItem >::iterator it;
1170     for (it=pFound->second.begin(); it!=pFound->second.end(); ++it)
1171     {
1172         uno::Reference< container::XIndexContainer > xTemp = xIndexContainer;
1173 
1174         ::rtl::OUString sParentNodeName = it->m_sParentNodeName;
1175         sal_Int32 nIndex = 0;
1176         do
1177         {
1178             ::rtl::OUString sToken = sParentNodeName.getToken(0, '|', nIndex).trim();
1179             if (sToken.getLength()<=0)
1180                 break;
1181 
1182             sal_Int32 nCount = xTemp->getCount();
1183             for (sal_Int32 i=0; i<nCount; ++i)
1184             {
1185                 ::rtl::OUString sCommandURL;
1186                 ::rtl::OUString sLabel;
1187                 uno::Reference< container::XIndexContainer > xChild;
1188 
1189                 uno::Sequence< beans::PropertyValue > aPropSeq;
1190                 xTemp->getByIndex(i) >>= aPropSeq;
1191                 for (sal_Int32 j=0; j<aPropSeq.getLength(); ++j)
1192                 {
1193                     ::rtl::OUString sPropName = aPropSeq[j].Name;
1194                     if (sPropName.equals(ITEM_DESCRIPTOR_COMMANDURL))
1195                         aPropSeq[j].Value >>= sCommandURL;
1196                     else if (sPropName.equals(ITEM_DESCRIPTOR_LABEL))
1197                         aPropSeq[j].Value >>= sLabel;
1198                     else if (sPropName.equals(ITEM_DESCRIPTOR_CONTAINER))
1199                         aPropSeq[j].Value >>= xChild;
1200                 }
1201 
1202                 if (sCommandURL == sToken)
1203                 {
1204                     xTemp = xChild;
1205                     break;
1206                 }
1207             }
1208 
1209         } while (nIndex>=0);
1210 
1211         if (nIndex == -1)
1212         {
1213             uno::Sequence< beans::PropertyValue > aPropSeq(3);
1214 
1215             aPropSeq[0].Name = ITEM_DESCRIPTOR_COMMANDURL;
1216             aPropSeq[0].Value <<= it->m_sCommandURL;
1217             aPropSeq[1].Name = ITEM_DESCRIPTOR_LABEL;
1218             aPropSeq[1].Value <<= retrieveLabelFromCommand(it->m_sCommandURL, sModuleIdentifier);
1219             aPropSeq[2].Name = ITEM_DESCRIPTOR_CONTAINER;
1220             aPropSeq[2].Value <<= it->m_xPopupMenu;
1221 
1222             if (it->m_sPrevSibling.getLength() == 0)
1223                 xTemp->insertByIndex(0, uno::makeAny(aPropSeq));
1224             else if (it->m_sPrevSibling.getLength() > 0)
1225             {
1226                 sal_Int32 nCount = xTemp->getCount();
1227                 sal_Int32 i = 0;
1228                 for (; i<nCount; ++i)
1229                 {
1230                     ::rtl::OUString sCmd;
1231                     uno::Sequence< beans::PropertyValue > aTempPropSeq;
1232                     xTemp->getByIndex(i) >>= aTempPropSeq;
1233                     for (sal_Int32 j=0; j<aTempPropSeq.getLength(); ++j)
1234                     {
1235                         if (aTempPropSeq[j].Name.equals(ITEM_DESCRIPTOR_COMMANDURL))
1236                         {
1237                             aTempPropSeq[j].Value >>= sCmd;
1238                             break;
1239                         }
1240                     }
1241 
1242                     if (sCmd.equals(it->m_sPrevSibling))
1243                         break;
1244                 }
1245 
1246                 xTemp->insertByIndex(i+1, uno::makeAny(aPropSeq));
1247             }
1248         }
1249     }
1250 
1251     uno::Reference< container::XIndexAccess > xIndexAccess(xIndexContainer, uno::UNO_QUERY);
1252     if (xIndexAccess.is())
1253         xCfgManager->replaceSettings(sResourceURL, xIndexAccess);
1254 
1255     uno::Reference< ui::XUIConfigurationPersistence > xUIConfigurationPersistence(xCfgManager, uno::UNO_QUERY);
1256     if (xUIConfigurationPersistence.is())
1257         xUIConfigurationPersistence->store();
1258 }
1259 
1260 uno::Reference< ui::XUIConfigurationManager > NewVersionUIInfo::getConfigManager(const ::rtl::OUString& sModuleShortName) const
1261 {
1262     uno::Reference< ui::XUIConfigurationManager > xCfgManager;
1263 
1264     for (sal_Int32 i=0; i<m_lCfgManagerSeq.getLength(); ++i)
1265     {
1266         if (m_lCfgManagerSeq[i].Name.equals(sModuleShortName))
1267         {
1268             m_lCfgManagerSeq[i].Value >>= xCfgManager;
1269             break;
1270         }
1271     }
1272 
1273     return xCfgManager;
1274 }
1275 
1276 uno::Reference< container::XIndexContainer > NewVersionUIInfo::getNewMenubarSettings(const ::rtl::OUString& sModuleShortName) const
1277 {
1278     uno::Reference< container::XIndexContainer > xNewMenuSettings;
1279 
1280     for (sal_Int32 i=0; i<m_lNewVersionMenubarSettingsSeq.getLength(); ++i)
1281     {
1282         if (m_lNewVersionMenubarSettingsSeq[i].Name.equals(sModuleShortName))
1283         {
1284             m_lNewVersionMenubarSettingsSeq[i].Value >>= xNewMenuSettings;
1285             break;
1286         }
1287     }
1288 
1289     return xNewMenuSettings;
1290 }
1291 
1292 uno::Reference< container::XIndexContainer > NewVersionUIInfo::getNewToolbarSettings(const ::rtl::OUString& sModuleShortName, const ::rtl::OUString& sToolbarName) const
1293 {
1294     uno::Reference< container::XIndexContainer > xNewToolbarSettings;
1295 
1296     for (sal_Int32 i=0; i<m_lNewVersionToolbarSettingsSeq.getLength(); ++i)
1297     {
1298         if (m_lNewVersionToolbarSettingsSeq[i].Name.equals(sModuleShortName))
1299         {
1300             uno::Sequence< beans::PropertyValue > lToolbarSettingsSeq;
1301             m_lNewVersionToolbarSettingsSeq[i].Value >>= lToolbarSettingsSeq;
1302             for (sal_Int32 j=0; j<lToolbarSettingsSeq.getLength(); ++j)
1303             {
1304                 if (lToolbarSettingsSeq[j].Name.equals(sToolbarName))
1305                 {
1306                     lToolbarSettingsSeq[j].Value >>= xNewToolbarSettings;
1307                     break;
1308                 }
1309             }
1310 
1311             break;
1312         }
1313     }
1314 
1315     return xNewToolbarSettings;
1316 }
1317 
1318 void NewVersionUIInfo::init(const ::std::vector< MigrationModuleInfo >& vModulesInfo)
1319 {
1320     m_lCfgManagerSeq.realloc(vModulesInfo.size());
1321     m_lNewVersionMenubarSettingsSeq.realloc(vModulesInfo.size());
1322     m_lNewVersionToolbarSettingsSeq.realloc(vModulesInfo.size());
1323 
1324     const ::rtl::OUString sModuleCfgSupplier = ::rtl::OUString::createFromAscii("com.sun.star.ui.ModuleUIConfigurationManagerSupplier");
1325     const ::rtl::OUString sMenubarResourceURL = ::rtl::OUString::createFromAscii("private:resource/menubar/menubar");
1326     const ::rtl::OUString sToolbarResourcePre = ::rtl::OUString::createFromAscii("private:resource/toolbar/");
1327 
1328     uno::Reference< ui::XModuleUIConfigurationManagerSupplier > xModuleCfgSupplier = uno::Reference< ui::XModuleUIConfigurationManagerSupplier >(::comphelper::getProcessServiceFactory()->createInstance(sModuleCfgSupplier), uno::UNO_QUERY);
1329 
1330     for (sal_uInt32 i=0; i<vModulesInfo.size(); ++i)
1331     {
1332         ::rtl::OUString sModuleIdentifier = mapModuleShortNameToIdentifier(vModulesInfo[i].sModuleShortName);
1333         if (sModuleIdentifier.getLength() > 0)
1334         {
1335             uno::Reference< ui::XUIConfigurationManager > xCfgManager = xModuleCfgSupplier->getUIConfigurationManager(sModuleIdentifier);
1336             m_lCfgManagerSeq[i].Name = vModulesInfo[i].sModuleShortName;
1337             m_lCfgManagerSeq[i].Value <<= xCfgManager;
1338 
1339             if (vModulesInfo[i].bHasMenubar)
1340             {
1341                 m_lNewVersionMenubarSettingsSeq[i].Name = vModulesInfo[i].sModuleShortName;
1342                 m_lNewVersionMenubarSettingsSeq[i].Value <<= xCfgManager->getSettings(sMenubarResourceURL, sal_True);
1343             }
1344 
1345             sal_Int32 nToolbars = vModulesInfo[i].m_vToolbars.size();
1346             if (nToolbars > 0)
1347             {
1348                 uno::Sequence< beans::PropertyValue > lPropSeq(nToolbars);
1349                 for (sal_Int32 j=0; j<nToolbars; ++j)
1350                 {
1351                     ::rtl::OUString sToolbarName = vModulesInfo[i].m_vToolbars[j];
1352                     ::rtl::OUString sToolbarResourceURL = sToolbarResourcePre + sToolbarName;
1353 
1354                     lPropSeq[j].Name = sToolbarName;
1355                     lPropSeq[j].Value <<= xCfgManager->getSettings(sToolbarResourceURL, sal_True);
1356                 }
1357 
1358                 m_lNewVersionToolbarSettingsSeq[i].Name = vModulesInfo[i].sModuleShortName;
1359                 m_lNewVersionToolbarSettingsSeq[i].Value <<= lPropSeq;
1360             }
1361         }
1362     }
1363 }
1364 
1365 } // namespace desktop
1366