merge the formfield patch from ooo-build
[ooovba.git] / desktop / source / migration / migration.cxx
blobc6b63fe1ffee30270422f9da710145ed2d244ab5
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: migration.cxx,v $
10 * $Revision: 1.13 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT uno::Any WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_desktop.hxx"
34 #include "migration.hxx"
35 #include "migration_impl.hxx"
36 #include "cfgfilter.hxx"
38 #include <unotools/textsearch.hxx>
39 #include <comphelper/processfactory.hxx>
40 #include <unotools/bootstrap.hxx>
41 #include <rtl/bootstrap.hxx>
42 #include <tools/config.hxx>
43 #include <i18npool/lang.h>
44 #include <tools/urlobj.hxx>
45 #include <osl/file.hxx>
46 #include <osl/mutex.hxx>
47 #include <ucbhelper/content.hxx>
48 #include <osl/security.hxx>
49 #include <unotools/configmgr.hxx>
51 #include <com/sun/star/lang/XInitialization.hpp>
52 #include <com/sun/star/task/XJob.hpp>
53 #include <com/sun/star/beans/NamedValue.hpp>
54 #include <com/sun/star/beans/XPropertySet.hpp>
55 #include <com/sun/star/configuration/backend/XLayer.hpp>
56 #include <com/sun/star/configuration/backend/XSingleLayerStratum.hpp>
57 #include <com/sun/star/util/XRefreshable.hpp>
58 #include <com/sun/star/util/XChangesBatch.hpp>
59 #include <com/sun/star/util/XStringSubstitution.hpp>
60 #include <com/sun/star/ui/XModuleUIConfigurationManagerSupplier.hpp>
61 #include <com/sun/star/ui/XAcceleratorConfiguration.hpp>
62 #include <com/sun/star/awt/Key.hpp>
63 #include <com/sun/star/awt/KeyEvent.hpp>
65 using namespace rtl;
66 using namespace osl;
67 using namespace std;
68 using namespace com::sun::star::task;
69 using namespace com::sun::star::lang;
70 using namespace com::sun::star::beans;
71 using namespace com::sun::star::util;
72 using namespace com::sun::star::container;
73 using namespace com::sun::star::configuration;
74 using namespace com::sun::star::configuration::backend;
75 using com::sun::star::uno::Exception;
76 using namespace com::sun::star;
78 #define ascii( asc ) \
79 ::rtl::OUString::intern( RTL_CONSTASCII_USTRINGPARAM( asc ) )
81 namespace desktop {
84 static MigrationImpl *pImpl = 0;
85 static Mutex aMutex;
86 static MigrationImpl *getImpl()
88 MutexGuard aGuard(aMutex);
89 if (pImpl == 0)
90 pImpl = new MigrationImpl(comphelper::getProcessServiceFactory());
91 return pImpl;
94 static void releaseImpl()
96 MutexGuard aGuard(aMutex);
97 if (pImpl != 0)
99 delete pImpl;
100 pImpl = 0;
105 // static main entry point for the migration process
106 void Migration::doMigration()
108 sal_Bool bResult = sal_False;
109 try {
110 bResult = getImpl()->doMigration();
111 } catch (Exception& e)
113 OString aMsg("doMigration() exception: ");
114 aMsg += OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US);
115 OSL_ENSURE(sal_False, aMsg.getStr());
117 OSL_ENSURE(bResult, "Migration has not been successfull");
118 // shut down migration framework
119 releaseImpl();
122 void Migration::cancelMigration()
124 releaseImpl();
127 sal_Bool Migration::checkMigration()
129 return getImpl()->checkMigration();
132 OUString Migration::getOldVersionName()
134 return getImpl()->getOldVersionName();
137 MigrationImpl::VersionNumber::VersionNumber() :
138 mnMajor(0), mnMinor(0), mnMicro(0)
142 MigrationImpl::VersionNumber::VersionNumber(sal_Int32 nMajor, sal_Int32 nMinor, sal_Int32 nMicro) :
143 mnMajor(nMajor), mnMinor(nMinor), mnMicro(nMicro)
147 OUString MigrationImpl::getOldVersionName()
149 return m_aInfo.productname;
152 static bool splitVersionString(const OUString& rVer, MigrationImpl::VersionNumber& rVerNum)
154 rVerNum.mnMajor = 0;
155 rVerNum.mnMinor = 0;
156 rVerNum.mnMicro = 0;
158 sal_Int32 nLen = rVer.getLength();
159 const sal_Unicode* pStr = rVer.getStr();
160 OUStringBuffer buf;
161 sal_uInt8 nPos = 0; // 0 = major; 1 = minor; 2 = micro
162 for (sal_Int32 i = 0; i < nLen; ++i)
164 const sal_Unicode c = pStr[i];
165 if (c >= sal_Unicode('0') && c <= sal_Unicode('9'))
166 buf.append(c);
167 else if (c == sal_Unicode('.'))
169 if (buf.getLength() == 0)
170 // no numbers.
171 return false;
173 sal_Int32 nTmp = buf.makeStringAndClear().toInt32();
174 if (nTmp < 0 || nTmp > 255)
175 // only 0 - 255 allowed in a version number.
176 return false;
178 switch (nPos)
180 case 0: rVerNum.mnMajor = static_cast<sal_uInt8>(nTmp); break;
181 case 1: rVerNum.mnMinor = static_cast<sal_uInt8>(nTmp); break;
182 case 2: rVerNum.mnMicro = static_cast<sal_uInt8>(nTmp); break;
185 nPos += 1;
186 if (nPos > 2)
187 return true;
189 else
190 return false;
193 return true;
196 /** returns -1 if rVer1 < rVer2, 0 if rVer1 == rVer2, or 1 if rVer1 >
197 rVer2. */
198 static short compareVersion(const MigrationImpl::VersionNumber& rVer1,
199 const MigrationImpl::VersionNumber& rVer2)
201 // major version
202 if (rVer1.mnMajor < rVer2.mnMajor)
203 return -1;
204 if (rVer1.mnMajor > rVer2.mnMajor)
205 return 1;
207 // minor version
208 if (rVer1.mnMinor < rVer2.mnMinor)
209 return -1;
210 if (rVer1.mnMinor > rVer2.mnMinor)
211 return 1;
213 // micro version
214 if (rVer1.mnMicro < rVer2.mnMicro)
215 return -1;
216 if (rVer1.mnMicro > rVer2.mnMicro)
217 return 1;
219 return 0;
222 static sal_Bool isMigrationNeeded(const OUString& rConfVerStr, const OUString& rAppVerStr,
223 MigrationImpl::VersionNumber& rConfVerNum,
224 MigrationImpl::VersionNumber& rAppVerNum)
226 if (!splitVersionString(rConfVerStr, rConfVerNum))
227 return sal_False;
229 if (!splitVersionString(rAppVerStr, rAppVerNum))
230 return sal_False;
232 #if OSL_DEBUG_LEVEL > 0
233 fprintf(stdout, "desktop::isMigrationNeeded: config ver = %d.%d.%d\n",
234 rConfVerNum.mnMajor,rConfVerNum.mnMinor,rConfVerNum.mnMicro);
236 fprintf(stdout, "desktop::isMigrationNeeded: app ver = %d.%d.%d\n",
237 rAppVerNum.mnMajor,rAppVerNum.mnMinor,rAppVerNum.mnMicro);
238 #endif
240 if (compareVersion(rConfVerNum, rAppVerNum) < 0)
241 return sal_True;
243 return sal_False;
246 sal_Bool MigrationImpl::checkMigration()
248 if (m_bMigrationCompleted)
249 // migration is already complete.
250 return sal_False;
254 uno::Reference< XPropertySet > aPropSet(getConfigAccess("org.openoffice.Setup/Product"), uno::UNO_QUERY_THROW);
255 uno::Any any = aPropSet->getPropertyValue(ascii("ooSetupVersionAboutBox"));
256 if (!(any >>= m_aAppVerStr))
257 // Current version unknown. Don't do migration (this should not happen).
258 return sal_False;
260 aPropSet.set(getConfigAccess("org.openoffice.Setup/Configuration"), uno::UNO_QUERY_THROW);
261 any = aPropSet->getPropertyValue(ascii("ooLastVersionTouched"));
262 OUString aLastVersion;
263 if (!(any >>= aLastVersion))
265 // last touched version unknown. Do the migration.
266 splitVersionString(m_aAppVerStr, m_aAppVerNum);
267 m_aConfigVerNum.mnMajor = 0;
268 m_aConfigVerNum.mnMinor = 0;
269 m_aConfigVerNum.mnMicro = 0;
270 return sal_True;
273 return isMigrationNeeded(aLastVersion, m_aAppVerStr, m_aConfigVerNum, m_aAppVerNum);
275 catch (const Exception&)
278 return sal_True;
281 MigrationImpl::MigrationImpl(const uno::Reference< XMultiServiceFactory >& xFactory)
282 : m_vrVersions(NULL)
283 , m_xFactory(xFactory)
284 , m_bMigrationCompleted(false)
288 MigrationImpl::~MigrationImpl()
293 sal_Bool MigrationImpl::doMigration()
295 #if OSL_DEBUG_LEVEL > 0
296 fprintf( stderr, "Migrating user configuration to newer OOo version.\n" );
297 #endif
299 sal_Bool result = sal_True;
301 if (compareVersion(m_aConfigVerNum, VersionNumber(3,0,0)) < 0)
305 initDirectoryMigration();
307 copyFiles();
309 // execute the migration items from Setup.xcu
310 // and refresh the cache
311 copyConfig();
312 refresh();
314 // execute custom migration services from Setup.xcu
315 // and refresh the cache
316 runServices();
317 refresh();
320 catch (...)
322 OString aMsg("An unexpected exception was thrown during migration");
323 aMsg += "\nOldVersion: " + OUStringToOString(m_aInfo.productname, RTL_TEXTENCODING_ASCII_US);
324 aMsg += "\nDataPath : " + OUStringToOString(m_aInfo.userdata, RTL_TEXTENCODING_ASCII_US);
325 OSL_ENSURE(sal_False, aMsg.getStr());
326 result = sal_False;
332 // migrate the configuration values.
333 transCalcFormulaConfig();
334 transKeyConfig();
335 cleanCSVImportCharSet();
337 catch (...)
339 result = sal_False;
341 // prevent running the migration multiple times
342 setMigrationCompleted();
343 return result;
346 void MigrationImpl::refresh()
348 uno::Reference< XRefreshable > xRefresh(m_xFactory->createInstance(
349 OUString::createFromAscii("com.sun.star.configuration.ConfigurationProvider")), uno::UNO_QUERY);
350 if (xRefresh.is())
351 xRefresh->refresh();
352 else
353 OSL_ENSURE(sal_False, "could not get XRefresh interface from default config provider. No refresh done.");
357 void MigrationImpl::transKeyConfig()
359 using namespace ::com::sun::star;
360 using namespace ::com::sun::star::ui;
362 #if OSL_DEBUG_LEVEL > 0
363 fprintf(stdout, "MigrationImpl::transKeyConfig: config ver = %ld.%ld.%ld\n",
364 long(m_aConfigVerNum.mnMajor), long(m_aConfigVerNum.mnMinor), long(m_aConfigVerNum.mnMicro));
366 fprintf(stdout, "MigrationImpl::transKeyConfig: app ver = %ld.%ld.%ld\n",
367 long(m_aAppVerNum.mnMajor), long(m_aAppVerNum.mnMinor), long(m_aAppVerNum.mnMicro));
368 #endif
370 if (compareVersion(m_aConfigVerNum, VersionNumber(2,4,0)) < 0)
372 // For config versions older than 2.4.0 only.
374 uno::Reference< XModuleUIConfigurationManagerSupplier > xModuleCfgSupplier(
375 m_xFactory->createInstance(
376 ascii("com.sun.star.ui.ModuleUIConfigurationManagerSupplier")), uno::UNO_QUERY_THROW);
378 // Grab the Calc configuration.
379 uno::Reference< XUIConfigurationManager > xConfigMgr =
380 xModuleCfgSupplier->getUIConfigurationManager(
381 ascii("com.sun.star.sheet.SpreadsheetDocument"));
383 if (xConfigMgr.is())
385 uno::Reference< XAcceleratorConfiguration > xScAccel(
386 xConfigMgr->getShortCutManager(), uno::UNO_QUERY_THROW);
388 // Backsapce key
389 awt::KeyEvent aBackEv;
390 aBackEv.KeyCode = awt::Key::BACKSPACE;
391 aBackEv.Modifiers = 0;
392 xScAccel->setKeyEvent(aBackEv, ascii(".uno:Delete"));
394 // Delete key
395 awt::KeyEvent aDeleteEv;
396 aDeleteEv.KeyCode = awt::Key::DELETE;
397 aDeleteEv.Modifiers = 0;
398 xScAccel->setKeyEvent(aDeleteEv, ascii(".uno:ClearContents"));
400 xScAccel->store();
405 void MigrationImpl::cleanCSVImportCharSet()
407 // Overwrite the character set value for CSV import to -1 (unset) on every
408 // upgrade, to prevent it from being incorrectly set to Unicode. (n#376473)
410 uno::Reference< XPropertySet > aPropSet;
411 aPropSet.set(getConfigAccess("org.openoffice.Office.Calc/Dialogs/CSVImport", true), uno::UNO_QUERY_THROW);
412 aPropSet->setPropertyValue(ascii("CharSet"), uno::makeAny(static_cast<sal_Int32>(-1)));
413 uno::Reference< XChangesBatch >(aPropSet, uno::UNO_QUERY_THROW)->commitChanges();
416 void MigrationImpl::transCalcFormulaConfig()
418 // Prior to 3.1.0, formula settings were stored in
419 // Calc/Calculate/FormulaSyntax. Migrate that to
420 // Calc/Formula/Syntax/Grammar.
422 if (compareVersion(m_aConfigVerNum, VersionNumber(3,1,0)) >= 0)
423 return;
427 uno::Reference<XPropertySet> xPropSet1(
428 getConfigAccess("org.openoffice.Office.Calc/Calculate/Other", true), uno::UNO_QUERY_THROW);
430 sal_Int32 nFormulaSyntax = 0;
431 xPropSet1->getPropertyValue(ascii("FormulaSyntax")) >>= nFormulaSyntax;
433 uno::Reference<XPropertySet> xPropSet2(
434 getConfigAccess("org.openoffice.Office.Calc/Formula/Syntax", true), uno::UNO_QUERY_THROW);
435 xPropSet2->setPropertyValue(ascii("Grammar"), uno::makeAny(nFormulaSyntax));
436 uno::Reference<XChangesBatch>(xPropSet2, uno::UNO_QUERY_THROW)->commitChanges();
438 catch (const Exception&)
443 void MigrationImpl::setMigrationCompleted()
447 uno::Reference< XPropertySet > aPropSet;
448 if (m_aAppVerStr.getLength() > 0)
450 aPropSet.set(getConfigAccess("org.openoffice.Setup/Configuration", true), uno::UNO_QUERY_THROW);
451 aPropSet->setPropertyValue(ascii("ooLastVersionTouched"), uno::makeAny(m_aAppVerStr));
452 uno::Reference< XChangesBatch >(aPropSet, uno::UNO_QUERY_THROW)->commitChanges();
455 m_bMigrationCompleted = true;
457 catch (const Exception&)
462 void MigrationImpl::initDirectoryMigration()
464 m_vrVersions.reset(new strings_v);
465 m_vrMigrations = readMigrationSteps();
466 m_aInfo = findInstallation();
467 m_vrFileList = compileFileList();
468 m_vrServiceList = compileServiceList();
471 migrations_vr MigrationImpl::readMigrationSteps()
474 // get supported version names
475 uno::Reference< XNameAccess > aMigrationAccess(getConfigAccess("org.openoffice.Setup/Migration"), uno::UNO_QUERY_THROW);
476 uno::Sequence< OUString > seqVersions;
477 aMigrationAccess->getByName(OUString::createFromAscii("SupportedVersions")) >>= seqVersions;
478 for (sal_Int32 i=0; i<seqVersions.getLength(); i++)
479 m_vrVersions->push_back(seqVersions[i].trim());
481 // get migration description from from org.openoffice.Setup/Migration
482 // and build vector of migration steps
483 uno::Reference< XNameAccess > theNameAccess(getConfigAccess("org.openoffice.Setup/Migration/MigrationSteps"), uno::UNO_QUERY_THROW);
484 uno::Sequence< OUString > seqMigrations = theNameAccess->getElementNames();
485 uno::Reference< XNameAccess > tmpAccess;
486 uno::Reference< XNameAccess > tmpAccess2;
487 uno::Sequence< OUString > tmpSeq;
488 migrations_vr vrMigrations(new migrations_v);
489 for (sal_Int32 i = 0; i < seqMigrations.getLength(); i++)
491 // get current migration step
492 theNameAccess->getByName(seqMigrations[i]) >>= tmpAccess;
493 // tmpStepPtr = new migration_step();
494 migration_step tmpStep;
495 tmpStep.name = seqMigrations[i];
497 // read included files from current step description
498 if (tmpAccess->getByName(OUString::createFromAscii("IncludedFiles")) >>= tmpSeq)
500 for (sal_Int32 j=0; j<tmpSeq.getLength(); j++)
501 tmpStep.includeFiles.push_back(tmpSeq[j]);
504 // exluded files...
505 if (tmpAccess->getByName(OUString::createFromAscii("ExcludedFiles")) >>= tmpSeq)
507 for (sal_Int32 j=0; j<tmpSeq.getLength(); j++)
508 tmpStep.excludeFiles.push_back(tmpSeq[j]);
511 // included nodes...
512 if (tmpAccess->getByName(OUString::createFromAscii("IncludedNodes")) >>= tmpSeq)
514 for (sal_Int32 j=0; j<tmpSeq.getLength(); j++)
515 tmpStep.includeConfig.push_back(tmpSeq[j]);
518 // excluded nodes...
519 if (tmpAccess->getByName(OUString::createFromAscii("ExcludedNodes")) >>= tmpSeq)
521 for (sal_Int32 j=0; j<tmpSeq.getLength(); j++)
522 tmpStep.excludeConfig.push_back(tmpSeq[j]);
525 // config components
526 if (tmpAccess->getByName(OUString::createFromAscii("ServiceConfigComponents")) >>= tmpSeq)
528 for (sal_Int32 j=0; j<tmpSeq.getLength(); j++)
529 tmpStep.configComponents.push_back(tmpSeq[j]);
533 // generic service
534 tmpAccess->getByName(OUString::createFromAscii("MigrationService")) >>= tmpStep.service;
536 vrMigrations->push_back(tmpStep);
538 return vrMigrations;
541 static FileBase::RC _checkAndCreateDirectory(INetURLObject& dirURL)
543 FileBase::RC result = Directory::create(dirURL.GetMainURL(INetURLObject::DECODE_TO_IURI));
544 if (result == FileBase::E_NOENT)
546 INetURLObject baseURL(dirURL);
547 baseURL.removeSegment();
548 _checkAndCreateDirectory(baseURL);
549 return Directory::create(dirURL.GetMainURL(INetURLObject::DECODE_TO_IURI));
550 } else
551 return result;
554 install_info MigrationImpl::findInstallation()
556 rtl::OUString aProductName;
557 uno::Any aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTNAME );
558 aRet >>= aProductName;
559 aProductName = aProductName.toAsciiLowerCase();
561 install_info aInfo;
562 strings_v::const_iterator i_ver = m_vrVersions->begin();
563 uno::Reference < util::XStringSubstitution > xSubst( ::comphelper::getProcessServiceFactory()->createInstance(::rtl::OUString::createFromAscii("com.sun.star.util.PathSubstitution")), uno::UNO_QUERY );
564 while (i_ver != m_vrVersions->end())
566 ::rtl::OUString aVersion, aProfileName;
567 sal_Int32 nSeparatorIndex = (*i_ver).indexOf('=');
568 if ( nSeparatorIndex != -1 )
570 aVersion = (*i_ver).copy( 0, nSeparatorIndex );
571 aProfileName = (*i_ver).copy( nSeparatorIndex+1 );
574 if ( aVersion.getLength() && aProfileName.getLength() &&
575 ( !aInfo.userdata.getLength() || !aProfileName.toAsciiLowerCase().compareTo( aProductName, aProductName.getLength() ) )
578 ::rtl::OUString aUserInst;
579 osl::Security().getConfigDir( aUserInst );
580 if ( aUserInst.getLength() && aUserInst[ aUserInst.getLength()-1 ] != '/' )
581 aUserInst += ::rtl::OUString::createFromAscii("/");
582 #ifdef UNX
583 // tribute to whoever had the "great" idea to use different names on Windows and Unix
584 aUserInst += ::rtl::OUString::createFromAscii(".");
585 #endif
586 aUserInst += aProfileName;
589 INetURLObject aObj(aUserInst);
590 ::ucbhelper::Content aCnt( aObj.GetMainURL( INetURLObject::NO_DECODE ), uno::Reference< ucb::XCommandEnvironment > () );
591 aCnt.isDocument();
592 aInfo.userdata = aObj.GetMainURL( INetURLObject::NO_DECODE );
593 aInfo.productname = aVersion;
595 catch( uno::Exception& ){}
597 i_ver++;
600 return aInfo;
603 strings_vr MigrationImpl::applyPatterns(const strings_v& vSet, const strings_v& vPatterns) const
605 using namespace utl;
606 strings_vr vrResult(new strings_v);
607 strings_v::const_iterator i_set;
608 strings_v::const_iterator i_pat = vPatterns.begin();
609 while (i_pat != vPatterns.end())
611 // find matches for this pattern in input set
612 // and copy them to the result
613 SearchParam param(*i_pat, SearchParam::SRCH_REGEXP);
614 TextSearch ts(param, LANGUAGE_DONTKNOW);
615 i_set = vSet.begin();
616 xub_StrLen start = 0;
617 xub_StrLen end = 0;
618 while (i_set != vSet.end())
620 end = (xub_StrLen)(i_set->getLength());
621 if (ts.SearchFrwrd(*i_set, &start, &end))
622 vrResult->push_back(*i_set);
623 i_set++;
625 i_pat++;
627 return vrResult;
630 strings_vr MigrationImpl::getAllFiles(const OUString& baseURL) const
632 using namespace osl;
633 strings_vr vrResult(new strings_v);
635 // get sub dirs
636 Directory dir(baseURL);
637 if (dir.open() == FileBase::E_None)
639 strings_v vSubDirs;
640 strings_vr vrSubResult;
642 // work through directory contents...
643 DirectoryItem item;
644 FileStatus fs(FileStatusMask_Type | FileStatusMask_FileURL);
645 while (dir.getNextItem(item) == FileBase::E_None)
647 if (item.getFileStatus(fs) == FileBase::E_None)
649 if (fs.getFileType() == FileStatus::Directory)
650 vSubDirs.push_back(fs.getFileURL());
651 else
652 vrResult->push_back(fs.getFileURL());
656 // recurse subfolders
657 strings_v::const_iterator i = vSubDirs.begin();
658 while (i != vSubDirs.end())
660 vrSubResult = getAllFiles(*i);
661 vrResult->insert(vrResult->end(), vrSubResult->begin(), vrSubResult->end());
662 i++;
665 return vrResult;
668 strings_vr MigrationImpl::compileFileList()
671 strings_vr vrResult(new strings_v);
672 strings_vr vrInclude;
673 strings_vr vrExclude;
674 strings_vr vrTemp;
676 #ifdef SAL_OS2
677 if (m_aInfo.userdata.getLength() == 0)
678 return vrResult;
679 #endif
681 // get a list of all files:
682 strings_vr vrFiles = getAllFiles(m_aInfo.userdata);
684 // get a file list result for each migration step
685 migrations_v::const_iterator i_migr = m_vrMigrations->begin();
686 while (i_migr != m_vrMigrations->end())
688 vrInclude = applyPatterns(*vrFiles, i_migr->includeFiles);
689 vrExclude = applyPatterns(*vrFiles, i_migr->excludeFiles);
690 substract(*vrInclude, *vrExclude);
691 vrResult->insert(vrResult->end(), vrInclude->begin(), vrInclude->end());
692 i_migr++;
694 return vrResult;
698 void MigrationImpl::copyConfig()
700 try {
701 // 1. get a list of all components from hierachy browser
702 uno::Reference< XJob > xBrowser(m_xFactory->createInstance(
703 OUString::createFromAscii("com.sun.star.configuration.backend.LocalHierarchyBrowser")), uno::UNO_QUERY_THROW);
705 uno::Sequence< NamedValue > seqArgs(2);
706 seqArgs[0] = NamedValue(
707 OUString::createFromAscii("LayerDataUrl"),
708 uno::makeAny(m_aInfo.userdata + OUString::createFromAscii("/user/registry")));
709 seqArgs[1] = NamedValue(
710 OUString::createFromAscii("FetchComponentNames"),
711 uno::makeAny(sal_True));
713 // execute the search
714 uno::Any aResult = xBrowser->execute(seqArgs);
715 uno::Sequence< OUString > seqComponents;
716 aResult >>= seqComponents;
717 OSL_ENSURE(seqComponents.getLength()>0, "MigrationImpl::copyConfig(): no config components available");
719 // 2. create an importer
720 uno::Reference< XJob > xImporter(m_xFactory->createInstance(
721 OUString::createFromAscii("com.sun.star.configuration.backend.LocalDataImporter")), uno::UNO_QUERY_THROW);
723 // 3. for each migration step...
724 uno::Sequence< NamedValue > importerArgs(3);
725 importerArgs[0] = NamedValue(
726 OUString::createFromAscii("LayerDataUrl"),
727 uno::makeAny(m_aInfo.userdata + OUString::createFromAscii("/user/registry")));
728 importerArgs[1] = NamedValue(
729 OUString::createFromAscii("LayerFilter"),
730 uno::Any());
731 importerArgs[2] = NamedValue(
732 OUString::createFromAscii("Component"),
733 uno::Any());
735 migrations_v::const_iterator i_mig = m_vrMigrations->begin();
736 while (i_mig != m_vrMigrations->end())
738 // a. create config filter for step
739 uno::Reference< XInitialization > xFilter(
740 new CConfigFilter(&(i_mig->includeConfig), &(i_mig->excludeConfig)));
741 importerArgs[1].Value = uno::makeAny(xFilter);
743 // b. run each importer with config filter
744 for (sal_Int32 i=0; i<seqComponents.getLength(); i++)
746 OUString component = seqComponents[i];
747 importerArgs[2].Value = uno::makeAny(seqComponents[i]);
748 try {
749 aResult = xImporter->execute(importerArgs);
750 Exception myException;
751 if (aResult >>= myException) throw myException;
752 } catch(Exception& aException) {
753 OString aMsg("Exception in config layer import.\ncomponent: ");
754 aMsg += OUStringToOString(seqComponents[i], RTL_TEXTENCODING_ASCII_US);
755 aMsg += "\nmessage: ";
756 aMsg += OUStringToOString(aException.Message, RTL_TEXTENCODING_ASCII_US);
757 OSL_ENSURE(sal_False, aMsg.getStr());
760 i_mig++;
763 catch (Exception& e)
765 OString aMsg("Exception in config layer import.\nmessage: ");
766 aMsg += OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US);
767 OSL_ENSURE(sal_False, aMsg.getStr());
773 // removes elements of vector 2 in vector 1
774 void MigrationImpl::substract(strings_v& va, const strings_v& vb_c) const
776 strings_v vb(vb_c);
777 // ensure uniqueness of entries
778 sort(va.begin(), va.end());
779 sort(vb.begin(), vb.end());
780 unique(va.begin(), va.end());
781 unique(vb.begin(), vb.end());
783 strings_v::const_iterator i_ex = vb.begin();
784 strings_v::iterator i_in;
785 strings_v::iterator i_next;
786 while (i_ex != vb.end())
788 i_in = va.begin();
789 while (i_in != va.end())
791 if ( *i_in == *i_ex)
793 i_next = i_in+1;
794 va.erase(i_in);
795 i_in = i_next;
796 // we can only find one match since we
797 // ensured uniquness of the entries. ergo:
798 break;
800 else
801 i_in++;
803 i_ex++;
807 uno::Reference< XNameAccess > MigrationImpl::getConfigAccess(const sal_Char* pPath, sal_Bool bUpdate)
809 uno::Reference< XNameAccess > xNameAccess;
810 try{
811 OUString sConfigSrvc = OUString::createFromAscii("com.sun.star.configuration.ConfigurationProvider");
812 OUString sAccessSrvc;
813 if (bUpdate)
814 sAccessSrvc = OUString::createFromAscii("com.sun.star.configuration.ConfigurationUpdateAccess");
815 else
816 sAccessSrvc = OUString::createFromAscii("com.sun.star.configuration.ConfigurationAccess");
818 OUString sConfigURL = OUString::createFromAscii(pPath);
820 // get configuration provider
821 uno::Reference< XMultiServiceFactory > theMSF = comphelper::getProcessServiceFactory();
822 uno::Reference< XMultiServiceFactory > theConfigProvider = uno::Reference< XMultiServiceFactory > (
823 theMSF->createInstance( sConfigSrvc ),uno::UNO_QUERY_THROW );
825 // access the provider
826 uno::Sequence< uno::Any > theArgs(1);
827 theArgs[ 0 ] <<= sConfigURL;
828 xNameAccess = uno::Reference< XNameAccess > (
829 theConfigProvider->createInstanceWithArguments(
830 sAccessSrvc, theArgs ), uno::UNO_QUERY_THROW );
831 } catch (com::sun::star::uno::Exception& e)
833 OString aMsg = OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US);
834 OSL_ENSURE(sal_False, aMsg.getStr());
836 return xNameAccess;
839 void MigrationImpl::copyFiles()
841 strings_v::const_iterator i_file = m_vrFileList->begin();
842 OUString localName;
843 OUString destName;
844 OUString userInstall;
845 utl::Bootstrap::PathStatus aStatus;
846 aStatus = utl::Bootstrap::locateUserInstallation(userInstall);
847 if (aStatus == utl::Bootstrap::PATH_EXISTS)
849 while (i_file != m_vrFileList->end())
852 // remove installation prefix from file
853 localName = i_file->copy(m_aInfo.userdata.getLength());
854 destName = userInstall + localName;
855 INetURLObject aURL(destName);
856 // check whether destination directory exists
857 aURL.removeSegment();
858 _checkAndCreateDirectory(aURL);
859 FileBase::RC copyResult = File::copy(*i_file, destName);
860 if (copyResult != FileBase::E_None)
862 OString msg("Cannot copy ");
863 msg += OUStringToOString(*i_file, RTL_TEXTENCODING_UTF8) + " to "
864 + OUStringToOString(destName, RTL_TEXTENCODING_UTF8);
865 OSL_ENSURE(sal_False, msg.getStr());
867 i_file++;
870 else
872 OSL_ENSURE(sal_False, "copyFiles: UserInstall does not exist");
876 void MigrationImpl::runServices()
879 //create stratum for old user layer
880 OUString aOldLayerURL = m_aInfo.userdata;
881 aOldLayerURL += OUString::createFromAscii("/user/registry");
882 OUString aStratumSvc = OUString::createFromAscii("com.sun.star.configuration.backend.LocalSingleStratum");
883 uno::Sequence< uno::Any > stratumArgs(1);
884 stratumArgs[0] = uno::makeAny(aOldLayerURL);
885 uno::Reference< XSingleLayerStratum> xStartum( m_xFactory->createInstanceWithArguments(
886 aStratumSvc, stratumArgs), uno::UNO_QUERY);
888 // Build argument array
889 uno::Sequence< uno::Any > seqArguments(3);
890 seqArguments[0] = uno::makeAny(NamedValue(
891 OUString::createFromAscii("Productname"),
892 uno::makeAny(m_aInfo.productname)));
893 seqArguments[1] = uno::makeAny(NamedValue(
894 OUString::createFromAscii("UserData"),
895 uno::makeAny(m_aInfo.userdata)));
898 // create an instance of every migration service
899 // and execute the migration job
900 uno::Reference< XJob > xMigrationJob;
902 migrations_v::const_iterator i_mig = m_vrMigrations->begin();
903 while (i_mig != m_vrMigrations->end())
905 if( i_mig->service.getLength() > 0)
910 // create access to old configuration components in the user layer
911 // that were requested by the migration service
912 uno::Sequence< NamedValue > seqComponents(i_mig->configComponents.size());
913 strings_v::const_iterator i_comp = i_mig->configComponents.begin();
914 sal_Int32 i = 0;
915 while (i_comp != i_mig->configComponents.end() && xStartum.is())
917 // create Layer for i_comp
918 seqComponents[i] = NamedValue(
919 *i_comp, uno::makeAny(xStartum->getLayer(*i_comp, OUString())));
921 // next component
922 i_comp++;
923 i++;
925 // set old config argument
926 seqArguments[2] = uno::makeAny(NamedValue(
927 OUString::createFromAscii("OldConfiguration"),
928 uno::makeAny(seqComponents)));
930 xMigrationJob = uno::Reference< XJob >(m_xFactory->createInstanceWithArguments(
931 i_mig->service, seqArguments), uno::UNO_QUERY_THROW);
933 xMigrationJob->execute(uno::Sequence< NamedValue >());
936 } catch (Exception& e)
938 OString aMsg("Execution of migration service failed (Exception caught).\nService: ");
939 aMsg += OUStringToOString(i_mig->service, RTL_TEXTENCODING_ASCII_US) + "\nMessage: ";
940 aMsg += OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US);
941 OSL_ENSURE(sal_False, aMsg.getStr());
942 } catch (...)
944 OString aMsg("Execution of migration service failed (Exception caught).\nService: ");
945 aMsg += OUStringToOString(i_mig->service, RTL_TEXTENCODING_ASCII_US) +
946 "\nNo message available";
947 OSL_ENSURE(sal_False, aMsg.getStr());
951 i_mig++;
956 strings_vr MigrationImpl::compileServiceList()
958 strings_vr vrResult(new strings_v);
959 migrations_v::const_iterator i_migr = m_vrMigrations->begin();
960 while (i_migr != m_vrMigrations->end())
962 vrResult->push_back(i_migr->service);
963 i_migr++;
965 return vrResult;
968 } // namespace desktop