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