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 $
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>
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 ) )
84 static MigrationImpl
*pImpl
= 0;
86 static MigrationImpl
*getImpl()
88 MutexGuard
aGuard(aMutex
);
90 pImpl
= new MigrationImpl(comphelper::getProcessServiceFactory());
94 static void releaseImpl()
96 MutexGuard
aGuard(aMutex
);
105 // static main entry point for the migration process
106 void Migration::doMigration()
108 sal_Bool bResult
= sal_False
;
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
122 void Migration::cancelMigration()
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
)
158 sal_Int32 nLen
= rVer
.getLength();
159 const sal_Unicode
* pStr
= rVer
.getStr();
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'))
167 else if (c
== sal_Unicode('.'))
169 if (buf
.getLength() == 0)
173 sal_Int32 nTmp
= buf
.makeStringAndClear().toInt32();
174 if (nTmp
< 0 || nTmp
> 255)
175 // only 0 - 255 allowed in a version number.
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;
196 /** returns -1 if rVer1 < rVer2, 0 if rVer1 == rVer2, or 1 if rVer1 >
198 static short compareVersion(const MigrationImpl::VersionNumber
& rVer1
,
199 const MigrationImpl::VersionNumber
& rVer2
)
202 if (rVer1
.mnMajor
< rVer2
.mnMajor
)
204 if (rVer1
.mnMajor
> rVer2
.mnMajor
)
208 if (rVer1
.mnMinor
< rVer2
.mnMinor
)
210 if (rVer1
.mnMinor
> rVer2
.mnMinor
)
214 if (rVer1
.mnMicro
< rVer2
.mnMicro
)
216 if (rVer1
.mnMicro
> rVer2
.mnMicro
)
222 static sal_Bool
isMigrationNeeded(const OUString
& rConfVerStr
, const OUString
& rAppVerStr
,
223 MigrationImpl::VersionNumber
& rConfVerNum
,
224 MigrationImpl::VersionNumber
& rAppVerNum
)
226 if (!splitVersionString(rConfVerStr
, rConfVerNum
))
229 if (!splitVersionString(rAppVerStr
, rAppVerNum
))
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
);
240 if (compareVersion(rConfVerNum
, rAppVerNum
) < 0)
246 sal_Bool
MigrationImpl::checkMigration()
248 if (m_bMigrationCompleted
)
249 // migration is already complete.
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).
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;
273 return isMigrationNeeded(aLastVersion
, m_aAppVerStr
, m_aConfigVerNum
, m_aAppVerNum
);
275 catch (const Exception
&)
281 MigrationImpl::MigrationImpl(const uno::Reference
< XMultiServiceFactory
>& xFactory
)
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" );
299 sal_Bool result
= sal_True
;
301 if (compareVersion(m_aConfigVerNum
, VersionNumber(3,0,0)) < 0)
305 initDirectoryMigration();
309 // execute the migration items from Setup.xcu
310 // and refresh the cache
314 // execute custom migration services from Setup.xcu
315 // and refresh the cache
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());
332 // migrate the configuration values.
333 transCalcFormulaConfig();
335 cleanCSVImportCharSet();
341 // prevent running the migration multiple times
342 setMigrationCompleted();
346 void MigrationImpl::refresh()
348 uno::Reference
< XRefreshable
> xRefresh(m_xFactory
->createInstance(
349 OUString::createFromAscii("com.sun.star.configuration.ConfigurationProvider")), uno::UNO_QUERY
);
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
));
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"));
385 uno::Reference
< XAcceleratorConfiguration
> xScAccel(
386 xConfigMgr
->getShortCutManager(), uno::UNO_QUERY_THROW
);
389 awt::KeyEvent aBackEv
;
390 aBackEv
.KeyCode
= awt::Key::BACKSPACE
;
391 aBackEv
.Modifiers
= 0;
392 xScAccel
->setKeyEvent(aBackEv
, ascii(".uno:Delete"));
395 awt::KeyEvent aDeleteEv
;
396 aDeleteEv
.KeyCode
= awt::Key::DELETE
;
397 aDeleteEv
.Modifiers
= 0;
398 xScAccel
->setKeyEvent(aDeleteEv
, ascii(".uno:ClearContents"));
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)
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
]);
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
]);
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
]);
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
]);
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
]);
534 tmpAccess
->getByName(OUString::createFromAscii("MigrationService")) >>= tmpStep
.service
;
536 vrMigrations
->push_back(tmpStep
);
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
));
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();
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("/");
583 // tribute to whoever had the "great" idea to use different names on Windows and Unix
584 aUserInst
+= ::rtl::OUString::createFromAscii(".");
586 aUserInst
+= aProfileName
;
589 INetURLObject
aObj(aUserInst
);
590 ::ucbhelper::Content
aCnt( aObj
.GetMainURL( INetURLObject::NO_DECODE
), uno::Reference
< ucb::XCommandEnvironment
> () );
592 aInfo
.userdata
= aObj
.GetMainURL( INetURLObject::NO_DECODE
);
593 aInfo
.productname
= aVersion
;
595 catch( uno::Exception
& ){}
603 strings_vr
MigrationImpl::applyPatterns(const strings_v
& vSet
, const strings_v
& vPatterns
) const
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;
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
);
630 strings_vr
MigrationImpl::getAllFiles(const OUString
& baseURL
) const
633 strings_vr
vrResult(new strings_v
);
636 Directory
dir(baseURL
);
637 if (dir
.open() == FileBase::E_None
)
640 strings_vr vrSubResult
;
642 // work through directory contents...
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());
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());
668 strings_vr
MigrationImpl::compileFileList()
671 strings_vr
vrResult(new strings_v
);
672 strings_vr vrInclude
;
673 strings_vr vrExclude
;
677 if (m_aInfo
.userdata
.getLength() == 0)
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());
698 void MigrationImpl::copyConfig()
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"),
731 importerArgs
[2] = NamedValue(
732 OUString::createFromAscii("Component"),
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
]);
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());
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
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())
789 while (i_in
!= va
.end())
796 // we can only find one match since we
797 // ensured uniquness of the entries. ergo:
807 uno::Reference
< XNameAccess
> MigrationImpl::getConfigAccess(const sal_Char
* pPath
, sal_Bool bUpdate
)
809 uno::Reference
< XNameAccess
> xNameAccess
;
811 OUString sConfigSrvc
= OUString::createFromAscii("com.sun.star.configuration.ConfigurationProvider");
812 OUString sAccessSrvc
;
814 sAccessSrvc
= OUString::createFromAscii("com.sun.star.configuration.ConfigurationUpdateAccess");
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());
839 void MigrationImpl::copyFiles()
841 strings_v::const_iterator i_file
= m_vrFileList
->begin();
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());
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();
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())));
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());
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());
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
);
968 } // namespace desktop