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 
retrieveLabelFromCommand(const::rtl::OUString & sCommand,const::rtl::OUString & sModuleIdentifier)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 
stripHotKey(const::rtl::OUString & str)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 
mapModuleShortNameToIdentifier(const::rtl::OUString & sShortName)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;
getImpl()194 static MigrationImpl *getImpl()
195 {
196     MutexGuard aGuard(aMutex);
197     if (pImpl == 0)
198         pImpl = new MigrationImpl(comphelper::getProcessServiceFactory());
199     return pImpl;
200 }
201 
releaseImpl()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
doMigration()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 successful");
225     // shut down migration framework
226     releaseImpl();
227 }
228 
cancelMigration()229 void Migration::cancelMigration()
230 {
231     releaseImpl();
232 }
233 
checkMigration()234 sal_Bool Migration::checkMigration()
235 {
236     return getImpl()->checkMigration();
237 }
238 
getOldVersionName()239 OUString Migration::getOldVersionName()
240 {
241     return getImpl()->getOldVersionName();
242 }
243 
getOldVersionName()244 OUString MigrationImpl::getOldVersionName()
245 {
246     return m_aInfo.productname;
247 }
248 
checkMigration()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 
MigrationImpl(const uno::Reference<XMultiServiceFactory> & xFactory)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 
~MigrationImpl()267 MigrationImpl::~MigrationImpl()
268 {
269 
270 }
271 
doMigration()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 
refresh()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 
setMigrationCompleted()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 
checkMigrationCompleted()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 
insertSorted(migrations_available & rAvailableMigrations,supported_migration & aSupportedMigration)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 
readAvailableMigrations(migrations_available & rAvailableMigrations)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 
readMigrationSteps(const::rtl::OUString & rMigrationName)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         // excluded 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 
_checkAndCreateDirectory(INetURLObject & dirURL)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 
findInstallation(const strings_v & rVersions)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 
findPreferedMigrationProcess(const migrations_available & rAvailableMigrations)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 
applyPatterns(const strings_v & vSet,const strings_v & vPatterns) const612 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 
getAllFiles(const OUString & baseURL) const639 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 
compileFileList()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 
getComponent(rtl::OUString const & path,rtl::OUString * component)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 
setToSeq(std::set<rtl::OUString> const & set)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 
copyConfig()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             if ( m_aInfo.productname.equals( OUString::createFromAscii("OpenOffice.org 3") ) )
772             {
773                 // OpenOffice.org 3 configuration file
774                 buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("/user/registrymodifications.xcu"));
775             }
776             else
777             {
778                 // OpenOffice.org 2 configuration files
779                 buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("/user/registry/data"));
780                 sal_Int32 n = 0;
781                 do {
782                     rtl::OUString seg(i->first.getToken(0, '.', n));
783                     rtl::OUString enc(
784                         rtl::Uri::encode(
785                             seg, rtl_UriCharClassPchar, rtl_UriEncodeStrict,
786                             RTL_TEXTENCODING_UTF8));
787                     if (enc.getLength() == 0 && seg.getLength() != 0) {
788                         OSL_TRACE(
789                             ("configuration migration component %s ignored (cannot"
790                              " be encoded as file path)"),
791                             rtl::OUStringToOString(
792                                 i->first, RTL_TEXTENCODING_UTF8).getStr());
793                         goto next;
794                     }
795                     buf.append(sal_Unicode('/'));
796                     buf.append(enc);
797                 } while (n >= 0);
798                 buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(".xcu"));
799             }
800             configuration::Update::get(
801                 comphelper::getProcessComponentContext())->
802                 insertModificationXcuFile(
803                     buf.makeStringAndClear(), setToSeq(i->second.includedPaths),
804                     setToSeq(i->second.excludedPaths));
805         } else {
806             OSL_TRACE(
807                 ("configuration migration component %s ignored (only excludes,"
808                  " no includes)"),
809                 rtl::OUStringToOString(
810                     i->first, RTL_TEXTENCODING_UTF8).getStr());
811         }
812     next:;
813     }
814 }
815 
816 // removes elements of vector 2 in vector 1
substract(strings_v & va,const strings_v & vb_c) const817 void MigrationImpl::substract(strings_v& va, const strings_v& vb_c) const
818 {
819     strings_v vb(vb_c);
820     // ensure uniqueness of entries
821     sort(va.begin(), va.end());
822     sort(vb.begin(), vb.end());
823     unique(va.begin(), va.end());
824     unique(vb.begin(), vb.end());
825 
826     strings_v::const_iterator i_ex = vb.begin();
827     strings_v::iterator i_in;
828     strings_v::iterator i_next;
829     while (i_ex != vb.end())
830     {
831         i_in = va.begin();
832         while (i_in != va.end())
833         {
834             if ( *i_in == *i_ex)
835             {
836                 i_next = i_in+1;
837                 va.erase(i_in);
838                 i_in = i_next;
839                 // we can only find one match since we
840                 // ensured uniqueness of the entries. ergo:
841                 break;
842             }
843             else
844                 i_in++;
845         }
846         i_ex++;
847     }
848 }
849 
getConfigAccess(const sal_Char * pPath,sal_Bool bUpdate)850 uno::Reference< XNameAccess > MigrationImpl::getConfigAccess(const sal_Char* pPath, sal_Bool bUpdate)
851 {
852 	uno::Reference< XNameAccess > xNameAccess;
853     try{
854         OUString sConfigSrvc = OUString::createFromAscii("com.sun.star.configuration.ConfigurationProvider");
855         OUString sAccessSrvc;
856         if (bUpdate)
857             sAccessSrvc = OUString::createFromAscii("com.sun.star.configuration.ConfigurationUpdateAccess");
858         else
859             sAccessSrvc = OUString::createFromAscii("com.sun.star.configuration.ConfigurationAccess");
860 
861         OUString sConfigURL = OUString::createFromAscii(pPath);
862 
863         // get configuration provider
864 		uno::Reference< XMultiServiceFactory > theMSF = comphelper::getProcessServiceFactory();
865 		uno::Reference< XMultiServiceFactory > theConfigProvider = uno::Reference< XMultiServiceFactory > (
866                 theMSF->createInstance( sConfigSrvc ),uno::UNO_QUERY_THROW );
867 
868         // access the provider
869         uno::Sequence< uno::Any > theArgs(1);
870         theArgs[ 0 ] <<= sConfigURL;
871 		xNameAccess = uno::Reference< XNameAccess > (
872                 theConfigProvider->createInstanceWithArguments(
873                 sAccessSrvc, theArgs ), uno::UNO_QUERY_THROW );
874     } catch (com::sun::star::uno::Exception& e)
875     {
876         OString aMsg = OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US);
877         OSL_ENSURE(sal_False, aMsg.getStr());
878     }
879     return xNameAccess;
880 }
881 
copyFiles()882 void MigrationImpl::copyFiles()
883 {
884     strings_v::const_iterator i_file = m_vrFileList->begin();
885     OUString localName;
886     OUString destName;
887     OUString userInstall;
888     utl::Bootstrap::PathStatus aStatus;
889     aStatus = utl::Bootstrap::locateUserInstallation(userInstall);
890     if (aStatus == utl::Bootstrap::PATH_EXISTS)
891     {
892         while (i_file != m_vrFileList->end())
893         {
894 
895             // remove installation prefix from file
896             localName = i_file->copy(m_aInfo.userdata.getLength());
897             destName = userInstall + localName;
898             INetURLObject aURL(destName);
899             // check whether destination directory exists
900             aURL.removeSegment();
901             _checkAndCreateDirectory(aURL);
902             FileBase::RC copyResult = File::copy(*i_file, destName);
903             if (copyResult != FileBase::E_None)
904             {
905                 OString msg("Cannot copy ");
906                 msg += OUStringToOString(*i_file, RTL_TEXTENCODING_UTF8) + " to "
907                     +  OUStringToOString(destName, RTL_TEXTENCODING_UTF8);
908                 OSL_ENSURE(sal_False, msg.getStr());
909             }
910             i_file++;
911         }
912     }
913     else
914     {
915         OSL_ENSURE(sal_False, "copyFiles: UserInstall does not exist");
916     }
917 }
918 
runServices()919 void MigrationImpl::runServices()
920 {
921     // Build argument array
922     uno::Sequence< uno::Any > seqArguments(3);
923     seqArguments[0] = uno::makeAny(NamedValue(
924         OUString::createFromAscii("Productname"),
925         uno::makeAny(m_aInfo.productname)));
926     seqArguments[1] = uno::makeAny(NamedValue(
927         OUString::createFromAscii("UserData"),
928         uno::makeAny(m_aInfo.userdata)));
929 
930 
931     // create an instance of every migration service
932     // and execute the migration job
933 	uno::Reference< XJob > xMigrationJob;
934 
935     migrations_v::const_iterator i_mig = m_vrMigrations->begin();
936     while (i_mig != m_vrMigrations->end())
937     {
938         if( i_mig->service.getLength() > 0)
939         {
940 
941             try
942             {
943                 // set black list for extension migration
944                 uno::Sequence< rtl::OUString > seqExtBlackList;
945                 sal_uInt32 nSize = i_mig->excludeExtensions.size();
946                 if ( nSize > 0 )
947                     seqExtBlackList = comphelper::arrayToSequence< ::rtl::OUString >(
948                         &i_mig->excludeExtensions[0], nSize );
949                 seqArguments[2] = uno::makeAny(NamedValue(
950                     OUString::createFromAscii("ExtensionBlackList"),
951                     uno::makeAny( seqExtBlackList )));
952 
953 				xMigrationJob = uno::Reference< XJob >(m_xFactory->createInstanceWithArguments(
954                     i_mig->service, seqArguments), uno::UNO_QUERY_THROW);
955 
956                 xMigrationJob->execute(uno::Sequence< NamedValue >());
957 
958 
959             } catch (Exception& e)
960             {
961                 OString aMsg("Execution of migration service failed (Exception caught).\nService: ");
962                 aMsg += OUStringToOString(i_mig->service, RTL_TEXTENCODING_ASCII_US) + "\nMessage: ";
963                 aMsg += OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US);
964                 OSL_ENSURE(sal_False, aMsg.getStr());
965             } catch (...)
966             {
967                 OString aMsg("Execution of migration service failed (Exception caught).\nService: ");
968                 aMsg += OUStringToOString(i_mig->service, RTL_TEXTENCODING_ASCII_US) +
969 					"\nNo message available";
970                 OSL_ENSURE(sal_False, aMsg.getStr());
971             }
972 
973         }
974         i_mig++;
975     }
976 }
977 
dectectUIChangesForAllModules() const978 ::std::vector< MigrationModuleInfo > MigrationImpl::dectectUIChangesForAllModules() const
979 {
980 	::std::vector< MigrationModuleInfo > vModulesInfo;
981 	const ::rtl::OUString MENUBAR = ::rtl::OUString::createFromAscii("menubar");
982 	const ::rtl::OUString TOOLBAR = ::rtl::OUString::createFromAscii("toolbar");
983 
984 	uno::Sequence< uno::Any > lArgs(2);
985 	lArgs[0] <<= m_aInfo.userdata + ::rtl::OUString::createFromAscii("/user/config/soffice.cfg/modules");
986 	lArgs[1] <<= embed::ElementModes::READ;
987 
988 	uno::Reference< lang::XSingleServiceFactory > xStorageFactory(m_xFactory->createInstance(::rtl::OUString::createFromAscii("com.sun.star.embed.FileSystemStorageFactory")), uno::UNO_QUERY);
989 	uno::Reference< embed::XStorage >             xModules;
990 
991 	xModules = uno::Reference< embed::XStorage >(xStorageFactory->createInstanceWithArguments(lArgs), uno::UNO_QUERY);
992 	if (!xModules.is())
993 		return vModulesInfo;
994 
995 	uno::Reference< container::XNameAccess > xAccess = uno::Reference< container::XNameAccess >(xModules, uno::UNO_QUERY);
996 	uno::Sequence< ::rtl::OUString > lNames = xAccess->getElementNames();
997 	sal_Int32 nLength = lNames.getLength();
998 	for (sal_Int32 i=0; i<nLength; ++i)
999 	{
1000         ::rtl::OUString sModuleShortName = lNames[i];
1001         uno::Reference< embed::XStorage > xModule = xModules->openStorageElement(sModuleShortName, embed::ElementModes::READ);
1002 		if (xModule.is())
1003 		{
1004 			MigrationModuleInfo aModuleInfo;
1005 
1006 			uno::Reference< embed::XStorage > xMenubar = xModule->openStorageElement(MENUBAR, embed::ElementModes::READ);
1007 			if (xMenubar.is())
1008 			{
1009 				uno::Reference< container::XNameAccess > xNameAccess = uno::Reference< container::XNameAccess >(xMenubar, uno::UNO_QUERY);
1010 				if (xNameAccess->getElementNames().getLength() > 0)
1011 				{
1012 					aModuleInfo.sModuleShortName = sModuleShortName;
1013 					aModuleInfo.bHasMenubar = sal_True;
1014 				}
1015 			}
1016 
1017 			uno::Reference< embed::XStorage > xToolbar = xModule->openStorageElement(TOOLBAR, embed::ElementModes::READ);
1018 			if (xToolbar.is())
1019 			{
1020 				const ::rtl::OUString RESOURCEURL_CUSTOM_ELEMENT = ::rtl::OUString::createFromAscii("custom_");
1021 				sal_Int32 nCustomLen = 7;
1022 
1023 				uno::Reference< container::XNameAccess > xNameAccess = uno::Reference< container::XNameAccess >(xToolbar, uno::UNO_QUERY);
1024 				::uno::Sequence< ::rtl::OUString > lToolbars = xNameAccess->getElementNames();
1025 				for (sal_Int32 j=0; j<lToolbars.getLength(); ++j)
1026 				{
1027                     ::rtl::OUString sToolbarName = lToolbars[j];
1028                     if (sToolbarName.getLength()>=nCustomLen &&
1029 						sToolbarName.copy(0, nCustomLen).equals(RESOURCEURL_CUSTOM_ELEMENT))
1030 						continue;
1031 
1032 					aModuleInfo.sModuleShortName = sModuleShortName;
1033 					sal_Int32 nIndex = sToolbarName.lastIndexOf('.');
1034 					if (nIndex > 0)
1035 					{
1036 						::rtl::OUString sExtension(sToolbarName.copy(nIndex));
1037 						::rtl::OUString sToolbarResourceName(sToolbarName.copy(0, nIndex));
1038 						if (sToolbarResourceName.getLength()>0 && sExtension.equalsAsciiL(".xml", 4))
1039 							aModuleInfo.m_vToolbars.push_back(sToolbarResourceName);
1040 					}
1041 				}
1042 			}
1043 
1044 			if (aModuleInfo.sModuleShortName.getLength()>0)
1045 				vModulesInfo.push_back(aModuleInfo);
1046 		}
1047 	}
1048 
1049 	return vModulesInfo;
1050 }
1051 
compareOldAndNewConfig(const::rtl::OUString & sParent,const uno::Reference<container::XIndexContainer> & xIndexOld,const uno::Reference<container::XIndexContainer> & xIndexNew,const::rtl::OUString & sResourceURL)1052 void MigrationImpl::compareOldAndNewConfig(const ::rtl::OUString& sParent,
1053 										   const uno::Reference< container::XIndexContainer >& xIndexOld,
1054 										   const uno::Reference< container::XIndexContainer >& xIndexNew,
1055 										   const ::rtl::OUString& sResourceURL)
1056 {
1057 	::std::vector< MigrationItem > vOldItems;
1058 	::std::vector< MigrationItem > vNewItems;
1059 	uno::Sequence< beans::PropertyValue > aProp;
1060 	sal_Int32 nOldCount = xIndexOld->getCount();
1061 	sal_Int32 nNewCount = xIndexNew->getCount();
1062 
1063 	for (int n=0; n<nOldCount; ++n)
1064 	{
1065 		MigrationItem aMigrationItem;
1066 		if (xIndexOld->getByIndex(n) >>= aProp)
1067 		{
1068 			for(int i=0; i<aProp.getLength(); ++i)
1069 			{
1070 				if (aProp[i].Name.equals(ITEM_DESCRIPTOR_COMMANDURL))
1071 					aProp[i].Value >>= aMigrationItem.m_sCommandURL;
1072 				else if (aProp[i].Name.equals(ITEM_DESCRIPTOR_CONTAINER))
1073 					aProp[i].Value >>= aMigrationItem.m_xPopupMenu;
1074 			}
1075 
1076 			if (aMigrationItem.m_sCommandURL.getLength())
1077 				vOldItems.push_back(aMigrationItem);
1078 		}
1079 	}
1080 
1081 	for (int n=0; n<nNewCount; ++n)
1082 	{
1083 		MigrationItem aMigrationItem;
1084 		if (xIndexNew->getByIndex(n) >>= aProp)
1085 		{
1086 			for(int i=0; i<aProp.getLength(); ++i)
1087 			{
1088 				if (aProp[i].Name.equals(ITEM_DESCRIPTOR_COMMANDURL))
1089 					aProp[i].Value >>= aMigrationItem.m_sCommandURL;
1090 				else if (aProp[i].Name.equals(ITEM_DESCRIPTOR_CONTAINER))
1091 					aProp[i].Value >>= aMigrationItem.m_xPopupMenu;
1092 			}
1093 
1094 			if (aMigrationItem.m_sCommandURL.getLength())
1095 				vNewItems.push_back(aMigrationItem);
1096 		}
1097 	}
1098 
1099 	::std::vector< MigrationItem >::iterator it;
1100 
1101 	::rtl::OUString sSibling;
1102 	for (it = vOldItems.begin(); it!=vOldItems.end(); ++it)
1103 	{
1104 		::std::vector< MigrationItem >::iterator pFound = ::std::find(vNewItems.begin(), vNewItems.end(), *it);
1105 		if (pFound != vNewItems.end() && it->m_xPopupMenu.is())
1106 		{
1107 			::rtl::OUString sName;
1108 			if (sParent.getLength()>0)
1109 				sName = sParent + MENU_SEPERATOR + it->m_sCommandURL;
1110 			else
1111 				sName = it->m_sCommandURL;
1112 			compareOldAndNewConfig(sName, it->m_xPopupMenu, pFound->m_xPopupMenu, sResourceURL);
1113 		}
1114 		else if (pFound == vNewItems.end())
1115 		{
1116 			MigrationItem aMigrationItem(sParent, sSibling, it->m_sCommandURL, it->m_xPopupMenu);
1117 			if (m_aOldVersionItemsHashMap.find(sResourceURL)==m_aOldVersionItemsHashMap.end())
1118 			{
1119 				::std::vector< MigrationItem > vMigrationItems;
1120 				m_aOldVersionItemsHashMap.insert(MigrationHashMap::value_type(sResourceURL, vMigrationItems));
1121 				m_aOldVersionItemsHashMap[sResourceURL].push_back(aMigrationItem);
1122 			}
1123 			else
1124 			{
1125 				if (::std::find(m_aOldVersionItemsHashMap[sResourceURL].begin(), m_aOldVersionItemsHashMap[sResourceURL].end(), aMigrationItem)==m_aOldVersionItemsHashMap[sResourceURL].end())
1126 					m_aOldVersionItemsHashMap[sResourceURL].push_back(aMigrationItem);
1127 			}
1128 		}
1129 
1130 		sSibling = it->m_sCommandURL;
1131 	}
1132 
1133 	::rtl::OUString sNewSibling;
1134 	uno::Reference< container::XIndexContainer > xPopup;
1135 	for (it = vNewItems.begin(); it!=vNewItems.end(); ++it)
1136 	{
1137 		::std::vector< MigrationItem >::iterator pFound = ::std::find(vOldItems.begin(), vOldItems.end(), *it);
1138 		if (pFound != vOldItems.end() && it->m_xPopupMenu.is())
1139 		{
1140 			::rtl::OUString sName;
1141 			if (sParent.getLength()>0)
1142 				sName = sParent + MENU_SEPERATOR + it->m_sCommandURL;
1143 			else
1144 				sName = it->m_sCommandURL;
1145 			compareOldAndNewConfig(sName, pFound->m_xPopupMenu, it->m_xPopupMenu, sResourceURL);
1146 		}
1147 		else if (::std::find(vOldItems.begin(), vOldItems.end(), *it) == vOldItems.end())
1148 		{
1149 			MigrationItem aMigrationItem(sParent, sSibling, it->m_sCommandURL, it->m_xPopupMenu);
1150 			if (m_aNewVersionItemsHashMap.find(sResourceURL)==m_aNewVersionItemsHashMap.end())
1151 			{
1152 				::std::vector< MigrationItem > vMigrationItems;
1153 				m_aNewVersionItemsHashMap.insert(MigrationHashMap::value_type(sResourceURL, vMigrationItems));
1154 				m_aNewVersionItemsHashMap[sResourceURL].push_back(aMigrationItem);
1155 			}
1156 			else
1157 			{
1158 				if (::std::find(m_aNewVersionItemsHashMap[sResourceURL].begin(), m_aNewVersionItemsHashMap[sResourceURL].end(), aMigrationItem)==m_aNewVersionItemsHashMap[sResourceURL].end())
1159 					m_aNewVersionItemsHashMap[sResourceURL].push_back(aMigrationItem);
1160 			}
1161 		}
1162 	}
1163 }
1164 
mergeOldToNewVersion(const uno::Reference<ui::XUIConfigurationManager> & xCfgManager,const uno::Reference<container::XIndexContainer> & xIndexContainer,const::rtl::OUString & sModuleIdentifier,const::rtl::OUString & sResourceURL)1165 void MigrationImpl::mergeOldToNewVersion(const uno::Reference< ui::XUIConfigurationManager >& xCfgManager,
1166 										 const uno::Reference< container::XIndexContainer>& xIndexContainer,
1167 										 const ::rtl::OUString& sModuleIdentifier,
1168 										 const ::rtl::OUString& sResourceURL)
1169 {
1170 	MigrationHashMap::iterator pFound = m_aOldVersionItemsHashMap.find(sResourceURL);
1171 	if (pFound==m_aOldVersionItemsHashMap.end())
1172 		return;
1173 
1174 	::std::vector< MigrationItem >::iterator it;
1175 	for (it=pFound->second.begin(); it!=pFound->second.end(); ++it)
1176 	{
1177 		uno::Reference< container::XIndexContainer > xTemp = xIndexContainer;
1178 
1179 		::rtl::OUString sParentNodeName = it->m_sParentNodeName;
1180 		sal_Int32 nIndex = 0;
1181 		do
1182 		{
1183 			::rtl::OUString sToken = sParentNodeName.getToken(0, '|', nIndex).trim();
1184 			if (sToken.getLength()<=0)
1185 				break;
1186 
1187 			sal_Int32 nCount = xTemp->getCount();
1188 			for (sal_Int32 i=0; i<nCount; ++i)
1189 			{
1190 				::rtl::OUString sCommandURL;
1191 				::rtl::OUString sLabel;
1192 				uno::Reference< container::XIndexContainer > xChild;
1193 
1194 				uno::Sequence< beans::PropertyValue > aPropSeq;
1195 				xTemp->getByIndex(i) >>= aPropSeq;
1196 				for (sal_Int32 j=0; j<aPropSeq.getLength(); ++j)
1197 				{
1198 					::rtl::OUString sPropName = aPropSeq[j].Name;
1199 					if (sPropName.equals(ITEM_DESCRIPTOR_COMMANDURL))
1200 						aPropSeq[j].Value >>= sCommandURL;
1201 					else if (sPropName.equals(ITEM_DESCRIPTOR_LABEL))
1202 						aPropSeq[j].Value >>= sLabel;
1203 					else if (sPropName.equals(ITEM_DESCRIPTOR_CONTAINER))
1204 						aPropSeq[j].Value >>= xChild;
1205 				}
1206 
1207 				if (sCommandURL == sToken)
1208 				{
1209 					xTemp = xChild;
1210 					break;
1211 				}
1212 			}
1213 
1214 		} while (nIndex>=0);
1215 
1216 		if (nIndex == -1)
1217 		{
1218 			uno::Sequence< beans::PropertyValue > aPropSeq(3);
1219 
1220 			aPropSeq[0].Name = ITEM_DESCRIPTOR_COMMANDURL;
1221 			aPropSeq[0].Value <<= it->m_sCommandURL;
1222 			aPropSeq[1].Name = ITEM_DESCRIPTOR_LABEL;
1223 			aPropSeq[1].Value <<= retrieveLabelFromCommand(it->m_sCommandURL, sModuleIdentifier);
1224 			aPropSeq[2].Name = ITEM_DESCRIPTOR_CONTAINER;
1225 			aPropSeq[2].Value <<= it->m_xPopupMenu;
1226 
1227 			if (it->m_sPrevSibling.getLength() == 0)
1228 				xTemp->insertByIndex(0, uno::makeAny(aPropSeq));
1229 			else if (it->m_sPrevSibling.getLength() > 0)
1230 			{
1231 				sal_Int32 nCount = xTemp->getCount();
1232 				sal_Int32 i = 0;
1233 				for (; i<nCount; ++i)
1234 				{
1235 					::rtl::OUString sCmd;
1236 					uno::Sequence< beans::PropertyValue > aTempPropSeq;
1237 					xTemp->getByIndex(i) >>= aTempPropSeq;
1238 					for (sal_Int32 j=0; j<aTempPropSeq.getLength(); ++j)
1239 					{
1240 						if (aTempPropSeq[j].Name.equals(ITEM_DESCRIPTOR_COMMANDURL))
1241 						{
1242 							aTempPropSeq[j].Value >>= sCmd;
1243 							break;
1244 						}
1245 					}
1246 
1247 					if (sCmd.equals(it->m_sPrevSibling))
1248 						break;
1249 				}
1250 
1251 				xTemp->insertByIndex(i+1, uno::makeAny(aPropSeq));
1252 			}
1253 		}
1254 	}
1255 
1256 	uno::Reference< container::XIndexAccess > xIndexAccess(xIndexContainer, uno::UNO_QUERY);
1257 	if (xIndexAccess.is())
1258 		xCfgManager->replaceSettings(sResourceURL, xIndexAccess);
1259 
1260 	uno::Reference< ui::XUIConfigurationPersistence > xUIConfigurationPersistence(xCfgManager, uno::UNO_QUERY);
1261 	if (xUIConfigurationPersistence.is())
1262 		xUIConfigurationPersistence->store();
1263 }
1264 
getConfigManager(const::rtl::OUString & sModuleShortName) const1265 uno::Reference< ui::XUIConfigurationManager > NewVersionUIInfo::getConfigManager(const ::rtl::OUString& sModuleShortName) const
1266 {
1267 	uno::Reference< ui::XUIConfigurationManager > xCfgManager;
1268 
1269 	for (sal_Int32 i=0; i<m_lCfgManagerSeq.getLength(); ++i)
1270 	{
1271 		if (m_lCfgManagerSeq[i].Name.equals(sModuleShortName))
1272 		{
1273 			m_lCfgManagerSeq[i].Value >>= xCfgManager;
1274 			break;
1275 		}
1276 	}
1277 
1278 	return xCfgManager;
1279 }
1280 
getNewMenubarSettings(const::rtl::OUString & sModuleShortName) const1281 uno::Reference< container::XIndexContainer > NewVersionUIInfo::getNewMenubarSettings(const ::rtl::OUString& sModuleShortName) const
1282 {
1283 	uno::Reference< container::XIndexContainer > xNewMenuSettings;
1284 
1285 	for (sal_Int32 i=0; i<m_lNewVersionMenubarSettingsSeq.getLength(); ++i)
1286 	{
1287 		if (m_lNewVersionMenubarSettingsSeq[i].Name.equals(sModuleShortName))
1288 		{
1289 			m_lNewVersionMenubarSettingsSeq[i].Value >>= xNewMenuSettings;
1290 			break;
1291 		}
1292 	}
1293 
1294 	return xNewMenuSettings;
1295 }
1296 
getNewToolbarSettings(const::rtl::OUString & sModuleShortName,const::rtl::OUString & sToolbarName) const1297 uno::Reference< container::XIndexContainer > NewVersionUIInfo::getNewToolbarSettings(const ::rtl::OUString& sModuleShortName, const ::rtl::OUString& sToolbarName) const
1298 {
1299 	uno::Reference< container::XIndexContainer > xNewToolbarSettings;
1300 
1301 	for (sal_Int32 i=0; i<m_lNewVersionToolbarSettingsSeq.getLength(); ++i)
1302 	{
1303 		if (m_lNewVersionToolbarSettingsSeq[i].Name.equals(sModuleShortName))
1304 		{
1305 			uno::Sequence< beans::PropertyValue > lToolbarSettingsSeq;
1306 			m_lNewVersionToolbarSettingsSeq[i].Value >>= lToolbarSettingsSeq;
1307 			for (sal_Int32 j=0; j<lToolbarSettingsSeq.getLength(); ++j)
1308 			{
1309 				if (lToolbarSettingsSeq[j].Name.equals(sToolbarName))
1310 				{
1311 					lToolbarSettingsSeq[j].Value >>= xNewToolbarSettings;
1312 					break;
1313 				}
1314 			}
1315 
1316 			break;
1317 		}
1318 	}
1319 
1320 	return xNewToolbarSettings;
1321 }
1322 
init(const::std::vector<MigrationModuleInfo> & vModulesInfo)1323 void NewVersionUIInfo::init(const ::std::vector< MigrationModuleInfo >& vModulesInfo)
1324 {
1325 	m_lCfgManagerSeq.realloc(vModulesInfo.size());
1326 	m_lNewVersionMenubarSettingsSeq.realloc(vModulesInfo.size());
1327 	m_lNewVersionToolbarSettingsSeq.realloc(vModulesInfo.size());
1328 
1329 	const ::rtl::OUString sModuleCfgSupplier = ::rtl::OUString::createFromAscii("com.sun.star.ui.ModuleUIConfigurationManagerSupplier");
1330 	const ::rtl::OUString sMenubarResourceURL = ::rtl::OUString::createFromAscii("private:resource/menubar/menubar");
1331 	const ::rtl::OUString sToolbarResourcePre = ::rtl::OUString::createFromAscii("private:resource/toolbar/");
1332 
1333 	uno::Reference< ui::XModuleUIConfigurationManagerSupplier > xModuleCfgSupplier = uno::Reference< ui::XModuleUIConfigurationManagerSupplier >(::comphelper::getProcessServiceFactory()->createInstance(sModuleCfgSupplier), uno::UNO_QUERY);
1334 
1335 	for (sal_uInt32 i=0; i<vModulesInfo.size(); ++i)
1336 	{
1337 		::rtl::OUString sModuleIdentifier = mapModuleShortNameToIdentifier(vModulesInfo[i].sModuleShortName);
1338 		if (sModuleIdentifier.getLength() > 0)
1339 		{
1340 			uno::Reference< ui::XUIConfigurationManager > xCfgManager = xModuleCfgSupplier->getUIConfigurationManager(sModuleIdentifier);
1341 			m_lCfgManagerSeq[i].Name = vModulesInfo[i].sModuleShortName;
1342 			m_lCfgManagerSeq[i].Value <<= xCfgManager;
1343 
1344 			if (vModulesInfo[i].bHasMenubar)
1345 			{
1346 				m_lNewVersionMenubarSettingsSeq[i].Name = vModulesInfo[i].sModuleShortName;
1347 				m_lNewVersionMenubarSettingsSeq[i].Value <<= xCfgManager->getSettings(sMenubarResourceURL, sal_True);
1348 			}
1349 
1350 			sal_Int32 nToolbars = vModulesInfo[i].m_vToolbars.size();
1351 			if (nToolbars > 0)
1352 			{
1353 				uno::Sequence< beans::PropertyValue > lPropSeq(nToolbars);
1354 				for (sal_Int32 j=0; j<nToolbars; ++j)
1355 				{
1356 					::rtl::OUString sToolbarName = vModulesInfo[i].m_vToolbars[j];
1357 					::rtl::OUString sToolbarResourceURL = sToolbarResourcePre + sToolbarName;
1358 
1359 					lPropSeq[j].Name = sToolbarName;
1360 					lPropSeq[j].Value <<= xCfgManager->getSettings(sToolbarResourceURL, sal_True);
1361 				}
1362 
1363 				m_lNewVersionToolbarSettingsSeq[i].Name = vModulesInfo[i].sModuleShortName;
1364 				m_lNewVersionToolbarSettingsSeq[i].Value <<= lPropSeq;
1365 			}
1366 		}
1367 	}
1368 }
1369 
1370 } // namespace desktop
1371 
1372