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