LibreOffice Module desktop (master)  1
migration.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <sal/config.h>
21 
22 #include <algorithm>
23 #include <iterator>
24 #include <map>
25 #include <new>
26 #include <set>
27 
28 #include <migration.hxx>
29 #include "migration_impl.hxx"
30 
31 #include <sal/log.hxx>
32 #include <unotools/textsearch.hxx>
34 #include <comphelper/sequence.hxx>
35 #include <unotools/bootstrap.hxx>
36 #include <rtl/bootstrap.hxx>
37 #include <rtl/uri.hxx>
38 #include <i18nlangtag/lang.h>
39 #include <tools/urlobj.hxx>
40 #include <osl/file.hxx>
41 #include <osl/security.hxx>
42 #include <unotools/configmgr.hxx>
43 
44 #include <com/sun/star/configuration/Update.hpp>
45 #include <com/sun/star/configuration/theDefaultProvider.hpp>
46 #include <com/sun/star/lang/XInitialization.hpp>
47 #include <com/sun/star/task/XJob.hpp>
48 #include <com/sun/star/beans/NamedValue.hpp>
49 #include <com/sun/star/beans/XPropertySet.hpp>
50 #include <com/sun/star/util/XRefreshable.hpp>
51 #include <com/sun/star/util/XChangesBatch.hpp>
52 #include <com/sun/star/util/XStringSubstitution.hpp>
53 #include <com/sun/star/embed/ElementModes.hpp>
54 #include <com/sun/star/embed/FileSystemStorageFactory.hpp>
55 #include <com/sun/star/embed/XStorage.hpp>
56 #include <com/sun/star/ui/theModuleUIConfigurationManagerSupplier.hpp>
57 #include <com/sun/star/frame/theUICommandDescription.hpp>
58 #include <com/sun/star/ui/UIConfigurationManager.hpp>
59 #include <com/sun/star/ui/XUIConfiguration.hpp>
60 #include <com/sun/star/ui/XUIConfigurationStorage.hpp>
61 #include <com/sun/star/ui/XUIConfigurationPersistence.hpp>
62 
63 using namespace osl;
64 using namespace std;
65 using namespace com::sun::star::task;
66 using namespace com::sun::star::lang;
67 using namespace com::sun::star::beans;
68 using namespace com::sun::star::util;
69 using namespace com::sun::star::container;
70 using com::sun::star::uno::Exception;
71 using namespace com::sun::star;
72 
73 
74 namespace desktop
75 {
76 
77 static const char ITEM_DESCRIPTOR_COMMANDURL[] = "CommandURL";
78 static const char ITEM_DESCRIPTOR_CONTAINER[] = "ItemDescriptorContainer";
79 static const char ITEM_DESCRIPTOR_LABEL[] = "Label";
80 
81 static OUString retrieveLabelFromCommand(const OUString& sCommand, const OUString& sModuleIdentifier)
82 {
83  OUString sLabel;
84 
85  uno::Reference< container::XNameAccess > xUICommands;
86  uno::Reference< container::XNameAccess > const xNameAccess(
87  frame::theUICommandDescription::get(
89  xNameAccess->getByName( sModuleIdentifier ) >>= xUICommands;
90  if (xUICommands.is()) {
91  if ( !sCommand.isEmpty() ) {
92  OUString aStr;
93  ::uno::Sequence< beans::PropertyValue > aPropSeq;
94  try {
95  uno::Any a( xUICommands->getByName( sCommand ));
96  if ( a >>= aPropSeq ) {
97  for ( sal_Int32 i = 0; i < aPropSeq.getLength(); i++ ) {
98  if ( aPropSeq[i].Name == "Label" ) {
99  aPropSeq[i].Value >>= aStr;
100  break;
101  }
102  }
103  }
104 
105  sLabel = aStr;
106  } catch (const container::NoSuchElementException&) {
107  sLabel = sCommand;
108  sal_Int32 nIndex = sLabel.indexOf(':');
109  if (nIndex>=0 && nIndex <= sLabel.getLength()-1)
110  sLabel = sLabel.copy(nIndex+1);
111  }
112 
113  }
114  }
115 
116  return sLabel;
117 }
118 
119 static OUString mapModuleShortNameToIdentifier(const OUString& sShortName)
120 {
121  OUString sIdentifier;
122 
123  if ( sShortName == "StartModule" )
124  sIdentifier = "com.sun.star.frame.StartModule";
125 
126  else if ( sShortName == "swriter" )
127  sIdentifier = "com.sun.star.text.TextDocument";
128 
129  else if ( sShortName == "scalc" )
130  sIdentifier = "com.sun.star.sheet.SpreadsheetDocument";
131 
132  else if ( sShortName == "sdraw" )
133  sIdentifier = "com.sun.star.drawing.DrawingDocument";
134 
135  else if ( sShortName == "simpress" )
136  sIdentifier = "com.sun.star.presentation.PresentationDocument";
137 
138  else if ( sShortName == "smath" )
139  sIdentifier = "com.sun.star.formula.FormulaProperties";
140 
141  else if ( sShortName == "schart" )
142  sIdentifier = "com.sun.star.chart2.ChartDocument";
143 
144  else if ( sShortName == "BasicIDE" )
145  sIdentifier = "com.sun.star.script.BasicIDE";
146 
147  else if ( sShortName == "dbapp" )
148  sIdentifier = "com.sun.star.sdb.OfficeDatabaseDocument";
149 
150  else if ( sShortName == "sglobal" )
151  sIdentifier = "com.sun.star.text.GlobalDocument";
152 
153  else if ( sShortName == "sweb" )
154  sIdentifier = "com.sun.star.text.WebDocument";
155 
156  else if ( sShortName == "swxform" )
157  sIdentifier = "com.sun.star.xforms.XMLFormDocument";
158 
159  else if ( sShortName == "sbibliography" )
160  sIdentifier = "com.sun.star.frame.Bibliography";
161 
162  return sIdentifier;
163 }
164 
165 bool MigrationImpl::alreadyMigrated()
166 {
167  OUString const MIGRATION_STAMP_NAME("/MIGRATED4");
168  OUString aStr = m_aInfo.userdata + MIGRATION_STAMP_NAME;
169  File aFile(aStr);
170  // create migration stamp, and/or check its existence
171  bool bRet = aFile.open (osl_File_OpenFlag_Write | osl_File_OpenFlag_Create | osl_File_OpenFlag_NoLock) == FileBase::E_EXIST;
172  SAL_INFO( "desktop.migration", "File '" << aStr << "' exists? " << bRet );
173  return bRet;
174 }
175 
176 bool MigrationImpl::initializeMigration()
177 {
178  bool bRet = false;
179 
180  if (!checkMigrationCompleted()) {
181  readAvailableMigrations(m_vMigrationsAvailable);
182  sal_Int32 nIndex = findPreferredMigrationProcess(m_vMigrationsAvailable);
183  // m_aInfo is now set to the preferred migration source
184  if ( nIndex >= 0 ) {
185  if (alreadyMigrated())
186  return false;
187  m_vrMigrations = readMigrationSteps(m_vMigrationsAvailable[nIndex].name);
188  }
189 
190  bRet = !m_aInfo.userdata.isEmpty();
191  }
192 
193  SAL_INFO( "desktop.migration", "Migration " << ( bRet ? "needed" : "not required" ) );
194 
195  return bRet;
196 }
197 
198 void Migration::migrateSettingsIfNecessary()
199 {
200  MigrationImpl aImpl;
201 
202  if (! aImpl.initializeMigration() )
203  return;
204 
205  bool bResult = false;
206  try {
207  bResult = aImpl.doMigration();
208  } catch (const Exception& e) {
209  SAL_WARN( "desktop", "doMigration(): " << e);
210  }
211  OSL_ENSURE(bResult, "Migration has not been successful");
212 }
213 
214 MigrationImpl::MigrationImpl()
215 {
216 }
217 
218 MigrationImpl::~MigrationImpl()
219 {
220 }
221 
222 // The main entry point for migrating settings
223 bool MigrationImpl::doMigration()
224 {
225  // compile file list for migration
226  m_vrFileList = compileFileList();
227 
228  bool result = false;
229  try {
230  NewVersionUIInfo aNewVersionUIInfo;
231  std::vector< MigrationModuleInfo > vModulesInfo = dectectUIChangesForAllModules();
232  aNewVersionUIInfo.init(vModulesInfo);
233 
234  copyFiles();
235 
236  const OUString sMenubarResourceURL("private:resource/menubar/menubar");
237  const OUString sToolbarResourcePre("private:resource/toolbar/");
238  for (MigrationModuleInfo & i : vModulesInfo) {
239  OUString sModuleIdentifier = mapModuleShortNameToIdentifier(i.sModuleShortName);
240  if (sModuleIdentifier.isEmpty())
241  continue;
242 
243 
244  OUString aOldCfgDataPath = m_aInfo.userdata + "/user/config/soffice.cfg/modules/" + i.sModuleShortName;
245  uno::Sequence< uno::Any > lArgs {uno::makeAny(aOldCfgDataPath), uno::makeAny(embed::ElementModes::READ)};
246 
247  uno::Reference< uno::XComponentContext > xContext(comphelper::getProcessComponentContext());
248  uno::Reference< lang::XSingleServiceFactory > xStorageFactory(embed::FileSystemStorageFactory::create(xContext));
249  uno::Reference< embed::XStorage > xModules(xStorageFactory->createInstanceWithArguments(lArgs), uno::UNO_QUERY);
250  uno::Reference< ui::XUIConfigurationManager2 > xOldCfgManager = ui::UIConfigurationManager::create(xContext);
251 
252  if ( xModules.is() ) {
253  xOldCfgManager->setStorage( xModules );
254  xOldCfgManager->reload();
255  }
256 
257  uno::Reference< ui::XUIConfigurationManager > xCfgManager = aNewVersionUIInfo.getConfigManager(i.sModuleShortName);
258 
259  if (i.bHasMenubar) {
260  uno::Reference< container::XIndexContainer > xOldVersionMenuSettings(xOldCfgManager->getSettings(sMenubarResourceURL, true), uno::UNO_QUERY);
261  uno::Reference< container::XIndexContainer > xNewVersionMenuSettings = aNewVersionUIInfo.getNewMenubarSettings(i.sModuleShortName);
262  compareOldAndNewConfig(OUString(), xOldVersionMenuSettings, xNewVersionMenuSettings, sMenubarResourceURL);
263  mergeOldToNewVersion(xCfgManager, xNewVersionMenuSettings, sModuleIdentifier, sMenubarResourceURL);
264  }
265 
266  sal_Int32 nToolbars = i.m_vToolbars.size();
267  if (nToolbars >0) {
268  for (sal_Int32 j=0; j<nToolbars; ++j) {
269  OUString sToolbarName = i.m_vToolbars[j];
270  OUString sToolbarResourceURL = sToolbarResourcePre + sToolbarName;
271 
272  uno::Reference< container::XIndexContainer > xOldVersionToolbarSettings(xOldCfgManager->getSettings(sToolbarResourceURL, true), uno::UNO_QUERY);
273  uno::Reference< container::XIndexContainer > xNewVersionToolbarSettings = aNewVersionUIInfo.getNewToolbarSettings(i.sModuleShortName, sToolbarName);
274  compareOldAndNewConfig(OUString(), xOldVersionToolbarSettings, xNewVersionToolbarSettings, sToolbarResourceURL);
275  mergeOldToNewVersion(xCfgManager, xNewVersionToolbarSettings, sModuleIdentifier, sToolbarResourceURL);
276  }
277  }
278 
279  m_aOldVersionItemsHashMap.clear();
280  }
281 
282  // execute the migration items from Setup.xcu
283  copyConfig();
284 
285  // execute custom migration services from Setup.xcu
286  // and refresh the cache
287  runServices();
288  uno::Reference< XRefreshable >(
289  configuration::theDefaultProvider::get(comphelper::getProcessComponentContext()),
290  uno::UNO_QUERY_THROW)->refresh();
291 
292  result = true;
293  } catch (css::uno::Exception & e) {
294  SAL_WARN(
295  "desktop.migration",
296  "ignored Exception \"" << e
297  << "\" while migrating from version \"" << m_aInfo.productname
298  << "\" data \"" << m_aInfo.userdata << "\"");
299  }
300 
301  // prevent running the migration multiple times
302  setMigrationCompleted();
303  return result;
304 }
305 
306 void MigrationImpl::setMigrationCompleted()
307 {
308  try {
309  uno::Reference< XPropertySet > aPropertySet(getConfigAccess("org.openoffice.Setup/Office", true), uno::UNO_QUERY_THROW);
310  aPropertySet->setPropertyValue("MigrationCompleted", uno::makeAny(true));
311  uno::Reference< XChangesBatch >(aPropertySet, uno::UNO_QUERY_THROW)->commitChanges();
312  } catch (...) {
313  // fail silently
314  }
315 }
316 
317 bool MigrationImpl::checkMigrationCompleted()
318 {
319  bool bMigrationCompleted = false;
320  try {
321  uno::Reference< XPropertySet > aPropertySet(
322  getConfigAccess("org.openoffice.Setup/Office"), uno::UNO_QUERY_THROW);
323  aPropertySet->getPropertyValue("MigrationCompleted") >>= bMigrationCompleted;
324 
325  if( !bMigrationCompleted && getenv("SAL_DISABLE_USERMIGRATION" ) ) {
326  // migration prevented - fake its success
327  setMigrationCompleted();
328  bMigrationCompleted = true;
329  }
330  } catch (const Exception&) {
331  // just return false...
332  }
333  SAL_INFO( "desktop.migration", "Migration " << ( bMigrationCompleted ? "already completed" : "not done" ) );
334 
335  return bMigrationCompleted;
336 }
337 
338 static void insertSorted(migrations_available& rAvailableMigrations, supported_migration const & aSupportedMigration)
339 {
340  migrations_available::iterator pIter = std::find_if(rAvailableMigrations.begin(), rAvailableMigrations.end(),
341  [&aSupportedMigration](const supported_migration& rMigration) { return rMigration.nPriority < aSupportedMigration.nPriority; });
342  if (pIter != rAvailableMigrations.end())
343  rAvailableMigrations.insert(pIter, aSupportedMigration );
344  else
345  rAvailableMigrations.push_back( aSupportedMigration );
346 }
347 
348 void MigrationImpl::readAvailableMigrations(migrations_available& rAvailableMigrations)
349 {
350  // get supported version names
351  uno::Reference< XNameAccess > aMigrationAccess(getConfigAccess("org.openoffice.Setup/Migration/SupportedVersions"), uno::UNO_QUERY_THROW);
352  uno::Sequence< OUString > seqSupportedVersions = aMigrationAccess->getElementNames();
353 
354  const OUString aVersionIdentifiers( "VersionIdentifiers" );
355  const OUString aPriorityIdentifier( "Priority" );
356 
357  for (sal_Int32 i=0; i<seqSupportedVersions.getLength(); i++) {
358  sal_Int32 nPriority( 0 );
359  uno::Sequence< OUString > seqVersions;
360  uno::Reference< XNameAccess > xMigrationData( aMigrationAccess->getByName(seqSupportedVersions[i]), uno::UNO_QUERY_THROW );
361  xMigrationData->getByName( aVersionIdentifiers ) >>= seqVersions;
362  xMigrationData->getByName( aPriorityIdentifier ) >>= nPriority;
363 
364  supported_migration aSupportedMigration;
365  aSupportedMigration.name = seqSupportedVersions[i];
366  aSupportedMigration.nPriority = nPriority;
367  for (sal_Int32 j=0; j<seqVersions.getLength(); j++)
368  aSupportedMigration.supported_versions.push_back(seqVersions[j].trim());
369  insertSorted( rAvailableMigrations, aSupportedMigration );
370  SAL_INFO( "desktop.migration", " available migration '" << aSupportedMigration.name << "'" );
371  }
372 }
373 
374 migrations_vr MigrationImpl::readMigrationSteps(const OUString& rMigrationName)
375 {
376  // get migration access
377  uno::Reference< XNameAccess > aMigrationAccess(getConfigAccess("org.openoffice.Setup/Migration/SupportedVersions"), uno::UNO_QUERY_THROW);
378  uno::Reference< XNameAccess > xMigrationData( aMigrationAccess->getByName(rMigrationName), uno::UNO_QUERY_THROW );
379 
380  // get migration description from org.openoffice.Setup/Migration
381  // and build vector of migration steps
382  uno::Reference< XNameAccess > theNameAccess(xMigrationData->getByName("MigrationSteps"), uno::UNO_QUERY_THROW);
383  uno::Reference< XNameAccess > tmpAccess;
384  uno::Sequence< OUString > tmpSeq;
385  migrations_vr vrMigrations(new migrations_v);
386  for (const OUString& rMigrationStep : theNameAccess->getElementNames()) {
387  // get current migration step
388  theNameAccess->getByName(rMigrationStep) >>= tmpAccess;
389  migration_step tmpStep;
390 
391  // read included files from current step description
392  if (tmpAccess->getByName("IncludedFiles") >>= tmpSeq) {
393  for (const OUString& rSeqEntry : tmpSeq)
394  tmpStep.includeFiles.push_back(rSeqEntry);
395  }
396 
397  // excluded files...
398  if (tmpAccess->getByName("ExcludedFiles") >>= tmpSeq) {
399  for (const OUString& rSeqEntry : tmpSeq)
400  tmpStep.excludeFiles.push_back(rSeqEntry);
401  }
402 
403  // included nodes...
404  if (tmpAccess->getByName("IncludedNodes") >>= tmpSeq) {
405  for (const OUString& rSeqEntry : tmpSeq)
406  tmpStep.includeConfig.push_back(rSeqEntry);
407  }
408 
409  // excluded nodes...
410  if (tmpAccess->getByName("ExcludedNodes") >>= tmpSeq) {
411  for (const OUString& rSeqEntry : tmpSeq)
412  tmpStep.excludeConfig.push_back(rSeqEntry);
413  }
414 
415  // excluded extensions...
416  if (tmpAccess->getByName("ExcludedExtensions") >>= tmpSeq) {
417  for (const OUString& rSeqEntry : tmpSeq)
418  tmpStep.excludeExtensions.push_back(rSeqEntry);
419  }
420 
421  // generic service
422  tmpAccess->getByName("MigrationService") >>= tmpStep.service;
423 
424  vrMigrations->push_back(tmpStep);
425  }
426  return vrMigrations;
427 }
428 
429 static FileBase::RC _checkAndCreateDirectory(INetURLObject const & dirURL)
430 {
432  if (result == FileBase::E_NOENT) {
433  INetURLObject baseURL(dirURL);
434  baseURL.removeSegment();
435  _checkAndCreateDirectory(baseURL);
437  } else
438  return result;
439 }
440 
441 #if defined UNX && ! defined MACOSX
442 
443 static const char XDG_CONFIG_PART[] = "/.config/";
444 
445 OUString MigrationImpl::preXDGConfigDir(const OUString& rConfigDir)
446 {
447  OUString aPreXDGConfigPath;
448  const char* pXDGCfgHome = getenv("XDG_CONFIG_HOME");
449 
450  // cater for XDG_CONFIG_HOME change
451  // If XDG_CONFIG_HOME is set then we;
452  // assume the user knows what they are doing ( room for improvement here, we could
453  // of course search the default config dir etc. also - but this is more complex,
454  // we would need to weigh results from the current config dir against matches in
455  // the 'old' config dir etc. ) - currently we just use the returned config dir.
456  // If XDG_CONFIG_HOME is NOT set;
457  // assume then we should now using the default $HOME/.config config location for
458  // our user profiles, however *all* previous libreoffice and openoffice.org
459  // configurations will be in the 'old' config directory and that's where we need
460  // to search - we convert the returned config dir to the 'old' dir
461  if ( !pXDGCfgHome && rConfigDir.endsWith( XDG_CONFIG_PART ) )
462  // remove trailing '.config/' but leave the terminating '/'
463  aPreXDGConfigPath = rConfigDir.copy( 0, rConfigDir.getLength() - sizeof( XDG_CONFIG_PART ) + 2 );
464  else
465  aPreXDGConfigPath = rConfigDir;
466 
467  // the application-specific config dir is no longer prefixed by '.' because it is hidden under ".config"
468  // we have to add the '.' for the pre-XDG directory names
469  aPreXDGConfigPath += ".";
470 
471  return aPreXDGConfigPath;
472 }
473 #endif
474 
475 void MigrationImpl::setInstallInfoIfExist(
476  install_info& aInfo,
477  const OUString& rConfigDir,
478  const OUString& rVersion)
479 {
480  OUString url(INetURLObject(rConfigDir).GetMainURL(INetURLObject::DecodeMechanism::NONE));
481  osl::DirectoryItem item;
482  osl::FileStatus stat(osl_FileStatus_Mask_Type);
483 
484  if (osl::DirectoryItem::get(url, item) == osl::FileBase::E_None
485  && item.getFileStatus(stat) == osl::FileBase::E_None
486  && stat.getFileType() == osl::FileStatus::Directory) {
487  aInfo.userdata = url;
488  aInfo.productname = rVersion;
489  }
490 }
491 
492 install_info MigrationImpl::findInstallation(const strings_v& rVersions)
493 {
494 
495  OUString aTopConfigDir;
496  osl::Security().getConfigDir( aTopConfigDir );
497  if ( !aTopConfigDir.isEmpty() && aTopConfigDir[ aTopConfigDir.getLength()-1 ] != '/' )
498  aTopConfigDir += "/";
499 
500 #if defined UNX && ! defined MACOSX
501  OUString aPreXDGTopConfigDir = preXDGConfigDir(aTopConfigDir);
502 #endif
503 
504  install_info aInfo;
505  for (auto const& elem : rVersions)
506  {
507  OUString aVersion, aProfileName;
508  sal_Int32 nSeparatorIndex = elem.indexOf('=');
509  if ( nSeparatorIndex != -1 ) {
510  aVersion = elem.copy( 0, nSeparatorIndex );
511  aProfileName = elem.copy( nSeparatorIndex+1 );
512  }
513 
514  if ( !aVersion.isEmpty() && !aProfileName.isEmpty() &&
515  ( aInfo.userdata.isEmpty() ||
516  aProfileName.equalsIgnoreAsciiCase(
518  setInstallInfoIfExist(aInfo, aTopConfigDir + aProfileName, aVersion);
519 #if defined UNX && ! defined MACOSX
520  //try preXDG path if the new one does not exist
521  if ( aInfo.userdata.isEmpty())
522  setInstallInfoIfExist(aInfo, aPreXDGTopConfigDir + aProfileName, aVersion);
523 #endif
524  }
525  }
526 
527  return aInfo;
528 }
529 
530 sal_Int32 MigrationImpl::findPreferredMigrationProcess(const migrations_available& rAvailableMigrations)
531 {
532  sal_Int32 nIndex( -1 );
533  sal_Int32 i( 0 );
534 
535  for (auto const& availableMigration : rAvailableMigrations)
536  {
537  install_info aInstallInfo = findInstallation(availableMigration.supported_versions);
538  if (!aInstallInfo.productname.isEmpty() ) {
539  m_aInfo = aInstallInfo;
540  nIndex = i;
541  break;
542  }
543  ++i;
544  }
545 
546  SAL_INFO( "desktop.migration", " preferred migration is from product '" << m_aInfo.productname << "'");
547  SAL_INFO( "desktop.migration", " and settings directory '" << m_aInfo.userdata << "'");
548 
549  return nIndex;
550 }
551 
552 strings_vr MigrationImpl::applyPatterns(const strings_v& vSet, const strings_v& vPatterns)
553 {
554  using namespace utl;
555  strings_vr vrResult(new strings_v);
556  for (auto const& pattern : vPatterns)
557  {
558  // find matches for this pattern in input set
559  // and copy them to the result
560  SearchParam param(pattern, SearchParam::SearchType::Regexp);
561  TextSearch ts(param, LANGUAGE_DONTKNOW);
562  sal_Int32 start = 0;
563  sal_Int32 end = 0;
564  for (auto const& elem : vSet)
565  {
566  end = elem.getLength();
567  if (ts.SearchForward(elem, &start, &end))
568  vrResult->push_back(elem);
569  }
570  }
571  return vrResult;
572 }
573 
574 strings_vr MigrationImpl::getAllFiles(const OUString& baseURL) const
575 {
576  strings_vr vrResult(new strings_v);
577 
578  // get sub dirs
579  Directory dir(baseURL);
580  if (dir.open() == FileBase::E_None) {
581  strings_v vSubDirs;
582  strings_vr vrSubResult;
583 
584  // work through directory contents...
585  DirectoryItem item;
586  FileStatus fs(osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileURL);
587  while (dir.getNextItem(item) == FileBase::E_None) {
588  if (item.getFileStatus(fs) == FileBase::E_None) {
589  if (fs.getFileType() == FileStatus::Directory)
590  vSubDirs.push_back(fs.getFileURL());
591  else
592  vrResult->push_back(fs.getFileURL());
593  }
594  }
595 
596  // recurse subfolders
597  for (auto const& subDir : vSubDirs)
598  {
599  vrSubResult = getAllFiles(subDir);
600  vrResult->insert(vrResult->end(), vrSubResult->begin(), vrSubResult->end());
601  }
602  }
603  return vrResult;
604 }
605 
606 namespace
607 {
608 
609 // removes elements of vector 2 in vector 1
610 strings_v subtract(strings_v const & va, strings_v const & vb)
611 {
612  strings_v a(va);
613  std::sort(a.begin(), a.end());
614  strings_v::iterator ae(std::unique(a.begin(), a.end()));
615  strings_v b(vb);
616  std::sort(b.begin(), b.end());
617  strings_v::iterator be(std::unique(b.begin(), b.end()));
618  strings_v c;
619  std::set_difference(a.begin(), ae, b.begin(), be, std::back_inserter(c));
620  return c;
621 }
622 
623 }
624 
625 strings_vr MigrationImpl::compileFileList()
626 {
627 
628  strings_vr vrResult(new strings_v);
629  strings_vr vrInclude;
630  strings_vr vrExclude;
631 
632  // get a list of all files:
633  strings_vr vrFiles = getAllFiles(m_aInfo.userdata);
634 
635  // get a file list result for each migration step
636  for (auto const& rMigration : *m_vrMigrations)
637  {
638  vrInclude = applyPatterns(*vrFiles, rMigration.includeFiles);
639  vrExclude = applyPatterns(*vrFiles, rMigration.excludeFiles);
640  strings_v sub(subtract(*vrInclude, *vrExclude));
641  vrResult->insert(vrResult->end(), sub.begin(), sub.end());
642  }
643  return vrResult;
644 }
645 
646 namespace
647 {
648 
649 struct componentParts {
650  std::set< OUString > includedPaths;
651  std::set< OUString > excludedPaths;
652 };
653 
654 typedef std::map< OUString, componentParts > Components;
655 
656 bool getComponent(OUString const & path, OUString * component)
657 {
658  OSL_ASSERT(component != nullptr);
659  if (path.isEmpty() || path[0] != '/') {
660  SAL_INFO( "desktop.migration", "configuration migration in/exclude path " << path << " ignored (does not start with slash)" );
661  return false;
662  }
663  sal_Int32 i = path.indexOf('/', 1);
664  *component = i < 0 ? path.copy(1) : path.copy(1, i - 1);
665  return true;
666 }
667 
668 }
669 
670 void MigrationImpl::copyConfig()
671 {
672  Components comps;
673  for (auto const& rMigrationStep : *m_vrMigrations) {
674  for (const OUString& rIncludePath : rMigrationStep.includeConfig) {
675  OUString comp;
676  if (getComponent(rIncludePath, &comp)) {
677  comps[comp].includedPaths.insert(rIncludePath);
678  }
679  }
680  for (const OUString& rExcludePath : rMigrationStep.excludeConfig) {
681  OUString comp;
682  if (getComponent(rExcludePath, &comp)) {
683  comps[comp].excludedPaths.insert(rExcludePath);
684  }
685  }
686  }
687 
688  // check if the shared registrymodifications.xcu file exists
689  bool bRegistryModificationsXcuExists = false;
690  OUString regFilePath(m_aInfo.userdata);
691  regFilePath += "/user/registrymodifications.xcu";
692  File regFile(regFilePath);
693  ::osl::FileBase::RC nError = regFile.open(osl_File_OpenFlag_Read);
694  if ( nError == ::osl::FileBase::E_None ) {
695  bRegistryModificationsXcuExists = true;
696  regFile.close();
697  }
698 
699  for (auto const& comp : comps)
700  {
701  if (!comp.second.includedPaths.empty()) {
702  if (!bRegistryModificationsXcuExists) {
703  // shared registrymodifications.xcu does not exists
704  // the configuration is split in many registry files
705  // determine the file names from the first element in included paths
706  OUStringBuffer buf(m_aInfo.userdata);
707  buf.append("/user/registry/data");
708  sal_Int32 n = 0;
709  do {
710  OUString seg(comp.first.getToken(0, '.', n));
711  OUString enc(
712  rtl::Uri::encode(
713  seg, rtl_UriCharClassPchar, rtl_UriEncodeStrict,
714  RTL_TEXTENCODING_UTF8));
715  if (enc.isEmpty() && !seg.isEmpty()) {
716  SAL_INFO( "desktop.migration", "configuration migration component " << comp.first << " ignored (cannot be encoded as file path)" );
717  goto next;
718  }
719  buf.append('/');
720  buf.append(enc);
721  } while (n >= 0);
722  buf.append(".xcu");
723  regFilePath = buf.toString();
724  }
725  configuration::Update::get(
727  insertModificationXcuFile(
728  regFilePath,
729  comphelper::containerToSequence(comp.second.includedPaths),
730  comphelper::containerToSequence(comp.second.excludedPaths));
731  } else {
732  SAL_INFO( "desktop.migration", "configuration migration component " << comp.first << " ignored (only excludes, no includes)" );
733  }
734 next:
735  ;
736  }
737 }
738 
739 uno::Reference< XNameAccess > MigrationImpl::getConfigAccess(const sal_Char* pPath, bool bUpdate)
740 {
741  uno::Reference< XNameAccess > xNameAccess;
742  try {
743  OUString sAccessSrvc;
744  if (bUpdate)
745  sAccessSrvc = "com.sun.star.configuration.ConfigurationUpdateAccess";
746  else
747  sAccessSrvc = "com.sun.star.configuration.ConfigurationAccess";
748 
749  OUString sConfigURL = OUString::createFromAscii(pPath);
750 
751  uno::Reference< XMultiServiceFactory > theConfigProvider(
752  configuration::theDefaultProvider::get(
754 
755  // access the provider
756  uno::Sequence< uno::Any > theArgs {uno::makeAny(sConfigURL)};
757  xNameAccess.set(
758  theConfigProvider->createInstanceWithArguments(
759  sAccessSrvc, theArgs ), uno::UNO_QUERY_THROW );
760  } catch (const css::uno::Exception& e) {
761  SAL_WARN(
762  "desktop.migration", "ignoring Exception \"" << e << "\"");
763  }
764  return xNameAccess;
765 }
766 
767 void MigrationImpl::copyFiles()
768 {
769  OUString localName;
770  OUString destName;
771  OUString userInstall;
773  aStatus = utl::Bootstrap::locateUserInstallation(userInstall);
774  if (aStatus == utl::Bootstrap::PATH_EXISTS) {
775  for (auto const& rFile : *m_vrFileList)
776  {
777  // remove installation prefix from file
778  localName = rFile.copy(m_aInfo.userdata.getLength());
779  if (localName.endsWith( "/autocorr/acor_.dat")) {
780  // Previous versions used an empty language tag for
781  // LANGUAGE_DONTKNOW with the "[All]" autocorrection entry.
782  // As of LibreOffice 4.0 it is 'und' for LANGUAGE_UNDETERMINED
783  // so the file name is "acor_und.dat".
784  localName = localName.copy( 0, localName.getLength() - 4) + "und.dat";
785  }
786  destName = userInstall + localName;
787  INetURLObject aURL(destName);
788  // check whether destination directory exists
789  aURL.removeSegment();
791  FileBase::RC copyResult = File::copy(rFile, destName);
792  if (copyResult != FileBase::E_None) {
793  SAL_WARN( "desktop", "Cannot copy " << rFile << " to " << destName);
794  }
795  }
796  } else {
797  OSL_FAIL("copyFiles: UserInstall does not exist");
798  }
799 }
800 
801 void MigrationImpl::runServices()
802 {
803  // Build argument array
804  uno::Sequence< uno::Any > seqArguments(3);
805  seqArguments[0] <<= NamedValue("Productname",
806  uno::makeAny(m_aInfo.productname));
807  seqArguments[1] <<= NamedValue("UserData",
808  uno::makeAny(m_aInfo.userdata));
809 
810 
811  // create an instance of every migration service
812  // and execute the migration job
813  uno::Reference< XJob > xMigrationJob;
814 
815  uno::Reference< uno::XComponentContext > xContext(comphelper::getProcessComponentContext());
816  for (auto const& rMigration : *m_vrMigrations)
817  {
818  if( !rMigration.service.isEmpty()) {
819 
820  try {
821  // set black list for extension migration
822  uno::Sequence< OUString > seqExtBlackList;
823  sal_uInt32 nSize = rMigration.excludeExtensions.size();
824  if ( nSize > 0 )
825  seqExtBlackList = comphelper::arrayToSequence< OUString >(
826  &rMigration.excludeExtensions[0], nSize );
827  seqArguments[2] <<= NamedValue("ExtensionBlackList",
828  uno::makeAny( seqExtBlackList ));
829 
830  xMigrationJob.set(
831  xContext->getServiceManager()->createInstanceWithArgumentsAndContext(rMigration.service, seqArguments, xContext),
832  uno::UNO_QUERY_THROW);
833 
834  xMigrationJob->execute(uno::Sequence< NamedValue >());
835 
836 
837  } catch (const Exception& e) {
838  SAL_WARN( "desktop", "Execution of migration service failed (Exception caught).\nService: "
839  << rMigration.service
840  << "\nMessage: " << e);
841  } catch (...) {
842  SAL_WARN( "desktop", "Execution of migration service failed (Exception caught).\nService: "
843  << rMigration.service << "\nNo message available");
844  }
845 
846  }
847  }
848 }
849 
850 std::vector< MigrationModuleInfo > MigrationImpl::dectectUIChangesForAllModules() const
851 {
852  std::vector< MigrationModuleInfo > vModulesInfo;
853  const OUString MENUBAR("menubar");
854  const OUString TOOLBAR("toolbar");
855 
856  uno::Sequence< uno::Any > lArgs {uno::makeAny(m_aInfo.userdata + "/user/config/soffice.cfg/modules"),
857  uno::makeAny(embed::ElementModes::READ)};
858 
859  uno::Reference< lang::XSingleServiceFactory > xStorageFactory(
861  uno::Reference< embed::XStorage > xModules;
862 
863  xModules.set(xStorageFactory->createInstanceWithArguments(lArgs), uno::UNO_QUERY);
864  if (!xModules.is())
865  return vModulesInfo;
866 
867  uno::Reference< container::XNameAccess > xAccess(xModules, uno::UNO_QUERY);
868  uno::Sequence< OUString > lNames = xAccess->getElementNames();
869  sal_Int32 nLength = lNames.getLength();
870  for (sal_Int32 i=0; i<nLength; ++i) {
871  OUString sModuleShortName = lNames[i];
872  uno::Reference< embed::XStorage > xModule = xModules->openStorageElement(sModuleShortName, embed::ElementModes::READ);
873  if (xModule.is()) {
874  MigrationModuleInfo aModuleInfo;
875 
876  uno::Reference< embed::XStorage > xMenubar = xModule->openStorageElement(MENUBAR, embed::ElementModes::READ);
877  if (xMenubar.is()) {
878  uno::Reference< container::XNameAccess > xNameAccess(xMenubar, uno::UNO_QUERY);
879  if (xNameAccess->getElementNames().getLength() > 0) {
880  aModuleInfo.sModuleShortName = sModuleShortName;
881  aModuleInfo.bHasMenubar = true;
882  }
883  }
884 
885  uno::Reference< embed::XStorage > xToolbar = xModule->openStorageElement(TOOLBAR, embed::ElementModes::READ);
886  if (xToolbar.is()) {
887  const OUString RESOURCEURL_CUSTOM_ELEMENT("custom_");
888  sal_Int32 nCustomLen = 7;
889 
890  uno::Reference< container::XNameAccess > xNameAccess(xToolbar, uno::UNO_QUERY);
891  ::uno::Sequence< OUString > lToolbars = xNameAccess->getElementNames();
892  for (sal_Int32 j=0; j<lToolbars.getLength(); ++j) {
893  OUString sToolbarName = lToolbars[j];
894  if (sToolbarName.getLength()>=nCustomLen &&
895  sToolbarName.copy(0, nCustomLen) == RESOURCEURL_CUSTOM_ELEMENT)
896  continue;
897 
898  aModuleInfo.sModuleShortName = sModuleShortName;
899  sal_Int32 nIndex = sToolbarName.lastIndexOf('.');
900  if (nIndex > 0) {
901  OUString sExtension(sToolbarName.copy(nIndex));
902  OUString sToolbarResourceName(sToolbarName.copy(0, nIndex));
903  if (!sToolbarResourceName.isEmpty() && sExtension == ".xml")
904  aModuleInfo.m_vToolbars.push_back(sToolbarResourceName);
905  }
906  }
907  }
908 
909  if (!aModuleInfo.sModuleShortName.isEmpty())
910  vModulesInfo.push_back(aModuleInfo);
911  }
912  }
913 
914  return vModulesInfo;
915 }
916 
917 void MigrationImpl::compareOldAndNewConfig(const OUString& sParent,
918  const uno::Reference< container::XIndexContainer >& xIndexOld,
919  const uno::Reference< container::XIndexContainer >& xIndexNew,
920  const OUString& sResourceURL)
921 {
922  const OUString MENU_SEPARATOR(" | ");
923 
924  std::vector< MigrationItem > vOldItems;
925  std::vector< MigrationItem > vNewItems;
926  uno::Sequence< beans::PropertyValue > aProp;
927  sal_Int32 nOldCount = xIndexOld->getCount();
928  sal_Int32 nNewCount = xIndexNew->getCount();
929 
930  for (int n=0; n<nOldCount; ++n) {
931  MigrationItem aMigrationItem;
932  if (xIndexOld->getByIndex(n) >>= aProp) {
933  for(int i=0; i<aProp.getLength(); ++i) {
934  if ( aProp[i].Name == ITEM_DESCRIPTOR_COMMANDURL )
935  aProp[i].Value >>= aMigrationItem.m_sCommandURL;
936  else if ( aProp[i].Name == ITEM_DESCRIPTOR_CONTAINER )
937  aProp[i].Value >>= aMigrationItem.m_xPopupMenu;
938  }
939 
940  if (!aMigrationItem.m_sCommandURL.isEmpty())
941  vOldItems.push_back(aMigrationItem);
942  }
943  }
944 
945  for (int n=0; n<nNewCount; ++n) {
946  MigrationItem aMigrationItem;
947  if (xIndexNew->getByIndex(n) >>= aProp) {
948  for(int i=0; i<aProp.getLength(); ++i) {
949  if ( aProp[i].Name == ITEM_DESCRIPTOR_COMMANDURL )
950  aProp[i].Value >>= aMigrationItem.m_sCommandURL;
951  else if ( aProp[i].Name == ITEM_DESCRIPTOR_CONTAINER )
952  aProp[i].Value >>= aMigrationItem.m_xPopupMenu;
953  }
954 
955  if (!aMigrationItem.m_sCommandURL.isEmpty())
956  vNewItems.push_back(aMigrationItem);
957  }
958  }
959 
960  OUString sSibling;
961  for (auto const& oldItem : vOldItems)
962  {
963  std::vector< MigrationItem >::iterator pFound = std::find(vNewItems.begin(), vNewItems.end(), oldItem);
964  if (pFound != vNewItems.end() && oldItem.m_xPopupMenu.is()) {
965  OUString sName;
966  if (!sParent.isEmpty())
967  sName = sParent + MENU_SEPARATOR + oldItem.m_sCommandURL;
968  else
969  sName = oldItem.m_sCommandURL;
970  compareOldAndNewConfig(sName, oldItem.m_xPopupMenu, pFound->m_xPopupMenu, sResourceURL);
971  } else if (pFound == vNewItems.end()) {
972  MigrationItem aMigrationItem(sParent, sSibling, oldItem.m_sCommandURL, oldItem.m_xPopupMenu);
973  if (m_aOldVersionItemsHashMap.find(sResourceURL)==m_aOldVersionItemsHashMap.end()) {
974  std::vector< MigrationItem > vMigrationItems;
975  m_aOldVersionItemsHashMap.emplace(sResourceURL, vMigrationItems);
976  m_aOldVersionItemsHashMap[sResourceURL].push_back(aMigrationItem);
977  } else {
978  if (std::find(m_aOldVersionItemsHashMap[sResourceURL].begin(), m_aOldVersionItemsHashMap[sResourceURL].end(), aMigrationItem)==m_aOldVersionItemsHashMap[sResourceURL].end())
979  m_aOldVersionItemsHashMap[sResourceURL].push_back(aMigrationItem);
980  }
981  }
982 
983  sSibling = oldItem.m_sCommandURL;
984  }
985 }
986 
987 void MigrationImpl::mergeOldToNewVersion(const uno::Reference< ui::XUIConfigurationManager >& xCfgManager,
988  const uno::Reference< container::XIndexContainer>& xIndexContainer,
989  const OUString& sModuleIdentifier,
990  const OUString& sResourceURL)
991 {
992  MigrationHashMap::iterator pFound = m_aOldVersionItemsHashMap.find(sResourceURL);
993  if (pFound==m_aOldVersionItemsHashMap.end())
994  return;
995 
996  for (auto const& elem : pFound->second)
997  {
998  uno::Reference< container::XIndexContainer > xTemp = xIndexContainer;
999 
1000  OUString sParentNodeName = elem.m_sParentNodeName;
1001  sal_Int32 nIndex = 0;
1002  do {
1003  OUString sToken = sParentNodeName.getToken(0, '|', nIndex).trim();
1004  if (sToken.isEmpty())
1005  break;
1006 
1007  sal_Int32 nCount = xTemp->getCount();
1008  for (sal_Int32 i=0; i<nCount; ++i) {
1009  OUString sCommandURL;
1010  OUString sLabel;
1011  uno::Reference< container::XIndexContainer > xChild;
1012 
1013  uno::Sequence< beans::PropertyValue > aPropSeq;
1014  xTemp->getByIndex(i) >>= aPropSeq;
1015  for (sal_Int32 j=0; j<aPropSeq.getLength(); ++j) {
1016  OUString sPropName = aPropSeq[j].Name;
1017  if ( sPropName == ITEM_DESCRIPTOR_COMMANDURL )
1018  aPropSeq[j].Value >>= sCommandURL;
1019  else if ( sPropName == ITEM_DESCRIPTOR_LABEL )
1020  aPropSeq[j].Value >>= sLabel;
1021  else if ( sPropName == ITEM_DESCRIPTOR_CONTAINER )
1022  aPropSeq[j].Value >>= xChild;
1023  }
1024 
1025  if (sCommandURL == sToken) {
1026  xTemp = xChild;
1027  break;
1028  }
1029  }
1030 
1031  } while (nIndex >= 0);
1032 
1033  if (nIndex == -1) {
1034  uno::Sequence< beans::PropertyValue > aPropSeq {
1035  beans::PropertyValue(ITEM_DESCRIPTOR_COMMANDURL, 0, uno::makeAny(elem.m_sCommandURL), beans::PropertyState_DIRECT_VALUE),
1036  beans::PropertyValue(ITEM_DESCRIPTOR_LABEL, 0, uno::makeAny(retrieveLabelFromCommand(elem.m_sCommandURL, sModuleIdentifier)), beans::PropertyState_DIRECT_VALUE),
1037  beans::PropertyValue(ITEM_DESCRIPTOR_CONTAINER, 0, uno::makeAny(elem.m_xPopupMenu), beans::PropertyState_DIRECT_VALUE)
1038  };
1039 
1040  if (elem.m_sPrevSibling.isEmpty())
1041  xTemp->insertByIndex(0, uno::makeAny(aPropSeq));
1042  else {
1043  sal_Int32 nCount = xTemp->getCount();
1044  sal_Int32 i = 0;
1045  for (; i<nCount; ++i) {
1046  OUString sCmd;
1047  uno::Sequence< beans::PropertyValue > aTempPropSeq;
1048  xTemp->getByIndex(i) >>= aTempPropSeq;
1049  for (sal_Int32 j=0; j<aTempPropSeq.getLength(); ++j) {
1050  if ( aTempPropSeq[j].Name == ITEM_DESCRIPTOR_COMMANDURL ) {
1051  aTempPropSeq[j].Value >>= sCmd;
1052  break;
1053  }
1054  }
1055 
1056  if (sCmd == elem.m_sPrevSibling)
1057  break;
1058  }
1059 
1060  xTemp->insertByIndex(i+1, uno::makeAny(aPropSeq));
1061  }
1062  }
1063  }
1064 
1065  uno::Reference< container::XIndexAccess > xIndexAccess(xIndexContainer, uno::UNO_QUERY);
1066  if (xIndexAccess.is())
1067  xCfgManager->replaceSettings(sResourceURL, xIndexAccess);
1068 
1069  uno::Reference< ui::XUIConfigurationPersistence > xUIConfigurationPersistence(xCfgManager, uno::UNO_QUERY);
1070  if (xUIConfigurationPersistence.is())
1071  xUIConfigurationPersistence->store();
1072 }
1073 
1074 uno::Reference< ui::XUIConfigurationManager > NewVersionUIInfo::getConfigManager(const OUString& sModuleShortName) const
1075 {
1076  uno::Reference< ui::XUIConfigurationManager > xCfgManager;
1077 
1078  for ( const css::beans::PropertyValue& rProp : m_lCfgManagerSeq) {
1079  if (rProp.Name == sModuleShortName) {
1080  rProp.Value >>= xCfgManager;
1081  break;
1082  }
1083  }
1084 
1085  return xCfgManager;
1086 }
1087 
1088 uno::Reference< container::XIndexContainer > NewVersionUIInfo::getNewMenubarSettings(const OUString& sModuleShortName) const
1089 {
1090  uno::Reference< container::XIndexContainer > xNewMenuSettings;
1091 
1092  for (sal_Int32 i=0; i<m_lNewVersionMenubarSettingsSeq.getLength(); ++i) {
1093  if (m_lNewVersionMenubarSettingsSeq[i].Name == sModuleShortName) {
1094  m_lNewVersionMenubarSettingsSeq[i].Value >>= xNewMenuSettings;
1095  break;
1096  }
1097  }
1098 
1099  return xNewMenuSettings;
1100 }
1101 
1102 uno::Reference< container::XIndexContainer > NewVersionUIInfo::getNewToolbarSettings(const OUString& sModuleShortName, const OUString& sToolbarName) const
1103 {
1104  uno::Reference< container::XIndexContainer > xNewToolbarSettings;
1105 
1106  for (sal_Int32 i=0; i<m_lNewVersionToolbarSettingsSeq.getLength(); ++i) {
1107  if (m_lNewVersionToolbarSettingsSeq[i].Name == sModuleShortName) {
1108  uno::Sequence< beans::PropertyValue > lToolbarSettingsSeq;
1109  m_lNewVersionToolbarSettingsSeq[i].Value >>= lToolbarSettingsSeq;
1110  for (sal_Int32 j=0; j<lToolbarSettingsSeq.getLength(); ++j) {
1111  if (lToolbarSettingsSeq[j].Name == sToolbarName) {
1112  lToolbarSettingsSeq[j].Value >>= xNewToolbarSettings;
1113  break;
1114  }
1115  }
1116 
1117  break;
1118  }
1119  }
1120 
1121  return xNewToolbarSettings;
1122 }
1123 
1124 void NewVersionUIInfo::init(const std::vector< MigrationModuleInfo >& vModulesInfo)
1125 {
1126  m_lCfgManagerSeq.resize(vModulesInfo.size());
1127  m_lNewVersionMenubarSettingsSeq.realloc(vModulesInfo.size());
1128  m_lNewVersionToolbarSettingsSeq.realloc(vModulesInfo.size());
1129 
1130  const OUString sMenubarResourceURL("private:resource/menubar/menubar");
1131  const OUString sToolbarResourcePre("private:resource/toolbar/");
1132 
1133  uno::Reference< ui::XModuleUIConfigurationManagerSupplier > xModuleCfgSupplier = ui::theModuleUIConfigurationManagerSupplier::get( ::comphelper::getProcessComponentContext() );
1134 
1135  for (size_t i=0; i<vModulesInfo.size(); ++i) {
1136  OUString sModuleIdentifier = mapModuleShortNameToIdentifier(vModulesInfo[i].sModuleShortName);
1137  if (!sModuleIdentifier.isEmpty()) {
1138  uno::Reference< ui::XUIConfigurationManager > xCfgManager = xModuleCfgSupplier->getUIConfigurationManager(sModuleIdentifier);
1139  m_lCfgManagerSeq[i].Name = vModulesInfo[i].sModuleShortName;
1140  m_lCfgManagerSeq[i].Value <<= xCfgManager;
1141 
1142  if (vModulesInfo[i].bHasMenubar) {
1143  m_lNewVersionMenubarSettingsSeq[i].Name = vModulesInfo[i].sModuleShortName;
1144  m_lNewVersionMenubarSettingsSeq[i].Value <<= xCfgManager->getSettings(sMenubarResourceURL, true);
1145  }
1146 
1147  sal_Int32 nToolbars = vModulesInfo[i].m_vToolbars.size();
1148  if (nToolbars > 0) {
1149  uno::Sequence< beans::PropertyValue > lPropSeq(nToolbars);
1150  for (sal_Int32 j=0; j<nToolbars; ++j) {
1151  OUString sToolbarName = vModulesInfo[i].m_vToolbars[j];
1152  OUString sToolbarResourceURL = sToolbarResourcePre + sToolbarName;
1153 
1154  lPropSeq[j].Name = sToolbarName;
1155  lPropSeq[j].Value <<= xCfgManager->getSettings(sToolbarResourceURL, true);
1156  }
1157 
1158  m_lNewVersionToolbarSettingsSeq[i].Name = vModulesInfo[i].sModuleShortName;
1159  m_lNewVersionToolbarSettingsSeq[i].Value <<= lPropSeq;
1160  }
1161  }
1162  }
1163 }
1164 
1165 } // namespace desktop
1166 
1167 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
std::unique_ptr< strings_v > strings_vr
static PathStatus locateUserInstallation(OUString &_rURL)
void init(const std::vector< MigrationModuleInfo > &vModulesInfo)
Definition: migration.cxx:1124
FileStatus
define the item, e.g.
static OUString mapModuleShortNameToIdentifier(const OUString &sShortName)
Definition: migration.cxx:119
std::set< OUString > excludedPaths
Definition: migration.cxx:651
OUString Name
std::vector< OUString > m_vToolbars
css::uno::Reference< css::container::XIndexContainer > getNewMenubarSettings(const OUString &sModuleShortName) const
Definition: migration.cxx:1088
css::uno::Reference< css::deployment::XPackageRegistry > create(css::uno::Reference< css::deployment::XPackageRegistry > const &xRootRegistry, OUString const &context, OUString const &cachePath, css::uno::Reference< css::uno::XComponentContext > const &xComponentContext)
Definition: app.cxx:167
static const char ITEM_DESCRIPTOR_CONTAINER[]
Definition: migration.cxx:78
css::uno::Reference< css::container::XIndexContainer > m_xPopupMenu
information for the UI elements to be migrated for one module
enumrange< T >::Iterator begin(enumrange< T >)
char sal_Char
static void insertSorted(migrations_available &rAvailableMigrations, supported_migration const &aSupportedMigration)
Definition: migration.cxx:338
std::vector< supported_migration > migrations_available
tuple comp
bool SearchForward(const OUString &rStr, sal_Int32 *pStart, sal_Int32 *pEnd, css::util::SearchResult *pRes=nullptr)
static OUString getProductName()
css::uno::Reference< css::container::XIndexContainer > getNewToolbarSettings(const OUString &sModuleShortName, const OUString &sToolbarName) const
Definition: migration.cxx:1102
OUString sName
MetadataImporterPluginType * result
int i
Object Value
#define LANGUAGE_DONTKNOW
static const char XDG_CONFIG_PART[]
Definition: migration.cxx:443
css::uno::Reference< css::ui::XUIConfigurationManager > getConfigManager(const OUString &sModuleShortName) const
Definition: migration.cxx:1074
enumrange< T >::Iterator end(enumrange< T >)
static const char ITEM_DESCRIPTOR_COMMANDURL[]
Definition: migration.cxx:77
OUString GetMainURL(DecodeMechanism eMechanism, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
static uno::Reference< css::uno::XComponentContext > xContext
Definition: init.cxx:1546
get the information before copying the ui configuration files of old version to new version ...
std::vector< uno::Reference< sheet::XSpreadsheetDocument > > Components
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
#define SAL_INFO(area, stream)
Reference< XComponentContext > getProcessComponentContext()
const char * name
std::set< OUString > includedPaths
Definition: migration.cxx:650
static const char ITEM_DESCRIPTOR_LABEL[]
Definition: migration.cxx:79
std::vector< migration_step > migrations_v
#define SAL_WARN(area, stream)
static OUString retrieveLabelFromCommand(const OUString &sCommand, const OUString &sModuleIdentifier)
Definition: migration.cxx:81
static FileBase::RC _checkAndCreateDirectory(INetURLObject const &dirURL)
Definition: migration.cxx:429
sal_Int32 const nLength
tuple next
aStr
std::vector< OUString > strings_v
bool removeSegment(sal_Int32 nIndex=LAST_SEGMENT, bool bIgnoreFinalSlash=true)
std::unique_ptr< migrations_v > migrations_vr