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