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