1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_desktop.hxx"
26
27 #include <map>
28 #include <new>
29 #include <set>
30
31 #include "migration.hxx"
32 #include "migration_impl.hxx"
33 #include "cfgfilter.hxx"
34
35 #include <unotools/textsearch.hxx>
36 #include <comphelper/processfactory.hxx>
37 #include <comphelper/sequence.hxx>
38 #include <unotools/bootstrap.hxx>
39 #include <rtl/bootstrap.hxx>
40 #include <rtl/uri.hxx>
41 #include <tools/config.hxx>
42 #include <i18npool/lang.h>
43 #include <tools/urlobj.hxx>
44 #include <osl/file.hxx>
45 #include <osl/mutex.hxx>
46 #include <ucbhelper/content.hxx>
47 #include <osl/security.hxx>
48 #include <unotools/configmgr.hxx>
49
50 #include <com/sun/star/configuration/Update.hpp>
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/util/XRefreshable.hpp>
56 #include <com/sun/star/util/XChangesBatch.hpp>
57 #include <com/sun/star/util/XStringSubstitution.hpp>
58 #include <com/sun/star/embed/ElementModes.hpp>
59 #include <com/sun/star/embed/XStorage.hpp>
60 #include <com/sun/star/ui/XUIConfiguration.hpp>
61 #include <com/sun/star/ui/XUIConfigurationStorage.hpp>
62 #include <com/sun/star/ui/XUIConfigurationPersistence.hpp>
63
64 using namespace rtl;
65 using namespace osl;
66 using namespace std;
67 using namespace com::sun::star::task;
68 using namespace com::sun::star::lang;
69 using namespace com::sun::star::beans;
70 using namespace com::sun::star::util;
71 using namespace com::sun::star::container;
72 using com::sun::star::uno::Exception;
73 using namespace com::sun::star;
74
75 namespace desktop {
76
77 static const ::rtl::OUString ITEM_DESCRIPTOR_COMMANDURL = ::rtl::OUString::createFromAscii("CommandURL");
78 static const ::rtl::OUString ITEM_DESCRIPTOR_CONTAINER = ::rtl::OUString::createFromAscii("ItemDescriptorContainer");
79 static const ::rtl::OUString ITEM_DESCRIPTOR_LABEL = ::rtl::OUString::createFromAscii("Label");
80
81 static const ::rtl::OUString MENU_SEPERATOR = ::rtl::OUString::createFromAscii(" | ");
82 static const ::rtl::OUString MENU_SUBMENU = ::rtl::OUString::createFromAscii("...");
83
retrieveLabelFromCommand(const::rtl::OUString & sCommand,const::rtl::OUString & sModuleIdentifier)84 ::rtl::OUString retrieveLabelFromCommand(const ::rtl::OUString& sCommand, const ::rtl::OUString& sModuleIdentifier)
85 {
86 ::rtl::OUString sLabel;
87
88 uno::Reference< container::XNameAccess > xUICommands;
89 uno::Reference< container::XNameAccess > xNameAccess( ::comphelper::getProcessServiceFactory()->createInstance( ::rtl::OUString::createFromAscii("com.sun.star.frame.UICommandDescription") ), uno::UNO_QUERY );
90 if ( xNameAccess.is() )
91 {
92 uno::Any a = xNameAccess->getByName( sModuleIdentifier );
93 a >>= xUICommands;
94 }
95 if (xUICommands.is())
96 {
97 if ( sCommand.getLength() > 0 )
98 {
99 rtl::OUString aStr;
100 ::uno::Sequence< beans::PropertyValue > aPropSeq;
101 try
102 {
103 uno::Any a( xUICommands->getByName( sCommand ));
104 if ( a >>= aPropSeq )
105 {
106 for ( sal_Int32 i = 0; i < aPropSeq.getLength(); i++ )
107 {
108 if ( aPropSeq[i].Name.equalsAscii( "Label" ))
109 {
110 aPropSeq[i].Value >>= aStr;
111 break;
112 }
113 }
114 }
115
116 sLabel = aStr;
117 }
118
119 catch(container::NoSuchElementException&)
120 {
121 sLabel = sCommand;
122 sal_Int32 nIndex = sLabel.indexOf(':');
123 if (nIndex>=0 && nIndex <= sLabel.getLength()-1)
124 sLabel = sLabel.copy(nIndex+1);
125 }
126
127 }
128 }
129
130 return sLabel;
131 }
132
stripHotKey(const::rtl::OUString & str)133 ::rtl::OUString stripHotKey( const ::rtl::OUString& str )
134 {
135 sal_Int32 index = str.indexOf( '~' );
136 if ( index == -1 )
137 {
138 return str;
139 }
140 else
141 {
142 return str.replaceAt( index, 1, ::rtl::OUString() );
143 }
144 }
145
mapModuleShortNameToIdentifier(const::rtl::OUString & sShortName)146 ::rtl::OUString mapModuleShortNameToIdentifier(const ::rtl::OUString& sShortName)
147 {
148 ::rtl::OUString sIdentifier;
149
150 if (sShortName.equals(::rtl::OUString::createFromAscii("StartModule")))
151 sIdentifier = ::rtl::OUString::createFromAscii("com.sun.star.frame.StartModule");
152
153 else if (sShortName.equals(::rtl::OUString::createFromAscii("swriter")))
154 sIdentifier = ::rtl::OUString::createFromAscii("com.sun.star.text.TextDocument");
155
156 else if (sShortName.equals(::rtl::OUString::createFromAscii("scalc")))
157 sIdentifier = ::rtl::OUString::createFromAscii("com.sun.star.sheet.SpreadsheetDocument");
158
159 else if (sShortName.equals(::rtl::OUString::createFromAscii("sdraw")))
160 sIdentifier = ::rtl::OUString::createFromAscii("com.sun.star.drawing.DrawingDocument");
161
162 else if (sShortName.equals(::rtl::OUString::createFromAscii("simpress")))
163 sIdentifier = ::rtl::OUString::createFromAscii("com.sun.star.presentation.PresentationDocument");
164
165 else if (sShortName.equals(::rtl::OUString::createFromAscii("smath")))
166 sIdentifier = ::rtl::OUString::createFromAscii("com.sun.star.formula.FormulaProperties");
167
168 else if (sShortName.equals(::rtl::OUString::createFromAscii("schart")))
169 sIdentifier = ::rtl::OUString::createFromAscii("com.sun.star.chart2.ChartDocument");
170
171 else if (sShortName.equals(::rtl::OUString::createFromAscii("BasicIDE")))
172 sIdentifier = ::rtl::OUString::createFromAscii("com.sun.star.script.BasicIDE");
173
174 else if (sShortName.equals(::rtl::OUString::createFromAscii("dbapp")))
175 sIdentifier = ::rtl::OUString::createFromAscii("com.sun.star.sdb.OfficeDatabaseDocument");
176
177 else if (sShortName.equals(::rtl::OUString::createFromAscii("sglobal")))
178 sIdentifier = ::rtl::OUString::createFromAscii("com.sun.star.text.GlobalDocument");
179
180 else if (sShortName.equals(::rtl::OUString::createFromAscii("sweb")))
181 sIdentifier = ::rtl::OUString::createFromAscii("com.sun.star.text.WebDocument");
182
183 else if (sShortName.equals(::rtl::OUString::createFromAscii("swxform")))
184 sIdentifier = ::rtl::OUString::createFromAscii("com.sun.star.xforms.XMLFormDocument");
185
186 else if (sShortName.equals(::rtl::OUString::createFromAscii("sbibliography")))
187 sIdentifier = ::rtl::OUString::createFromAscii("com.sun.star.frame.Bibliography");
188
189 return sIdentifier;
190 }
191
192 static MigrationImpl *pImpl = 0;
193 static Mutex aMutex;
getImpl()194 static MigrationImpl *getImpl()
195 {
196 MutexGuard aGuard(aMutex);
197 if (pImpl == 0)
198 pImpl = new MigrationImpl(comphelper::getProcessServiceFactory());
199 return pImpl;
200 }
201
releaseImpl()202 static void releaseImpl()
203 {
204 MutexGuard aGuard(aMutex);
205 if (pImpl != 0)
206 {
207 delete pImpl;
208 pImpl = 0;
209 }
210 }
211
212 // static main entry point for the migration process
doMigration()213 void Migration::doMigration()
214 {
215 sal_Bool bResult = sal_False;
216 try {
217 bResult = getImpl()->doMigration();
218 } catch (Exception& e)
219 {
220 OString aMsg("doMigration() exception: ");
221 aMsg += OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US);
222 OSL_ENSURE(sal_False, aMsg.getStr());
223 }
224 OSL_ENSURE(bResult, "Migration has not been successfull");
225 // shut down migration framework
226 releaseImpl();
227 }
228
cancelMigration()229 void Migration::cancelMigration()
230 {
231 releaseImpl();
232 }
233
checkMigration()234 sal_Bool Migration::checkMigration()
235 {
236 return getImpl()->checkMigration();
237 }
238
getOldVersionName()239 OUString Migration::getOldVersionName()
240 {
241 return getImpl()->getOldVersionName();
242 }
243
getOldVersionName()244 OUString MigrationImpl::getOldVersionName()
245 {
246 return m_aInfo.productname;
247 }
248
checkMigration()249 sal_Bool MigrationImpl::checkMigration()
250 {
251 if (m_aInfo.userdata.getLength() > 0 && ! checkMigrationCompleted())
252 return sal_True;
253 else
254 return sal_False;
255 }
256
MigrationImpl(const uno::Reference<XMultiServiceFactory> & xFactory)257 MigrationImpl::MigrationImpl(const uno::Reference< XMultiServiceFactory >& xFactory)
258 : m_vrVersions(new strings_v)
259 , m_xFactory(xFactory)
260 {
261 readAvailableMigrations(m_vMigrationsAvailable);
262 sal_Int32 nIndex = findPreferedMigrationProcess(m_vMigrationsAvailable);
263 if ( nIndex >= 0 )
264 m_vrMigrations = readMigrationSteps(m_vMigrationsAvailable[nIndex].name);
265 }
266
~MigrationImpl()267 MigrationImpl::~MigrationImpl()
268 {
269
270 }
271
doMigration()272 sal_Bool MigrationImpl::doMigration()
273 {
274 // compile file list for migration
275 m_vrFileList = compileFileList();
276
277 sal_Bool result = sal_False;
278 try
279 {
280 NewVersionUIInfo aNewVersionUIInfo;
281 ::std::vector< MigrationModuleInfo > vModulesInfo = dectectUIChangesForAllModules();
282 aNewVersionUIInfo.init(vModulesInfo);
283
284 copyFiles();
285
286 const ::rtl::OUString sMenubarResourceURL = ::rtl::OUString::createFromAscii("private:resource/menubar/menubar");
287 const ::rtl::OUString sToolbarResourcePre = ::rtl::OUString::createFromAscii("private:resource/toolbar/");
288 for (sal_uInt32 i=0; i<vModulesInfo.size(); ++i)
289 {
290 ::rtl::OUString sModuleIdentifier = mapModuleShortNameToIdentifier(vModulesInfo[i].sModuleShortName);
291 if (sModuleIdentifier.getLength()==0)
292 continue;
293
294 uno::Sequence< uno::Any > lArgs(2);
295 ::rtl::OUString aOldCfgDataPath = m_aInfo.userdata + ::rtl::OUString::createFromAscii("/user/config/soffice.cfg/modules/");
296 lArgs[0] <<= aOldCfgDataPath + vModulesInfo[i].sModuleShortName;
297 lArgs[1] <<= embed::ElementModes::READ;
298
299 uno::Reference< lang::XSingleServiceFactory > xStorageFactory(m_xFactory->createInstance(::rtl::OUString::createFromAscii("com.sun.star.embed.FileSystemStorageFactory")), uno::UNO_QUERY);
300 uno::Reference< embed::XStorage > xModules;
301
302 xModules = uno::Reference< embed::XStorage >(xStorageFactory->createInstanceWithArguments(lArgs), uno::UNO_QUERY);
303 uno::Reference< ui::XUIConfigurationManager > xOldCfgManager( m_xFactory->createInstance( rtl::OUString::createFromAscii("com.sun.star.ui.UIConfigurationManager")), uno::UNO_QUERY );
304 uno::Reference< ui::XUIConfigurationStorage > xOldCfgStorage( xOldCfgManager, uno::UNO_QUERY );
305 uno::Reference< ui::XUIConfigurationPersistence > xOldCfgPersistence( xOldCfgManager, uno::UNO_QUERY );
306
307 if ( xOldCfgStorage.is() && xOldCfgPersistence.is() && xModules.is() )
308 {
309 xOldCfgStorage->setStorage( xModules );
310 xOldCfgPersistence->reload();
311 }
312
313 uno::Reference< ui::XUIConfigurationManager > xCfgManager = aNewVersionUIInfo.getConfigManager(vModulesInfo[i].sModuleShortName);
314
315 if (vModulesInfo[i].bHasMenubar)
316 {
317 uno::Reference< container::XIndexContainer > xOldVersionMenuSettings = uno::Reference< container::XIndexContainer >(xOldCfgManager->getSettings(sMenubarResourceURL, sal_True), uno::UNO_QUERY);
318 uno::Reference< container::XIndexContainer > xNewVersionMenuSettings = aNewVersionUIInfo.getNewMenubarSettings(vModulesInfo[i].sModuleShortName);
319 ::rtl::OUString sParent;
320 compareOldAndNewConfig(sParent, xOldVersionMenuSettings, xNewVersionMenuSettings, sMenubarResourceURL);
321 mergeOldToNewVersion(xCfgManager, xNewVersionMenuSettings, sModuleIdentifier, sMenubarResourceURL);
322 }
323
324 sal_Int32 nToolbars = vModulesInfo[i].m_vToolbars.size();
325 if (nToolbars >0)
326 {
327 for (sal_Int32 j=0; j<nToolbars; ++j)
328 {
329 ::rtl::OUString sToolbarName = vModulesInfo[i].m_vToolbars[j];
330 ::rtl::OUString sToolbarResourceURL = sToolbarResourcePre + sToolbarName;
331
332 uno::Reference< container::XIndexContainer > xOldVersionToolbarSettings = uno::Reference< container::XIndexContainer >(xOldCfgManager->getSettings(sToolbarResourceURL, sal_True), uno::UNO_QUERY);
333 uno::Reference< container::XIndexContainer > xNewVersionToolbarSettings = aNewVersionUIInfo.getNewToolbarSettings(vModulesInfo[i].sModuleShortName, sToolbarName);
334 ::rtl::OUString sParent;
335 compareOldAndNewConfig(sParent, xOldVersionToolbarSettings, xNewVersionToolbarSettings, sToolbarResourceURL);
336 mergeOldToNewVersion(xCfgManager, xNewVersionToolbarSettings, sModuleIdentifier, sToolbarResourceURL);
337 }
338 }
339
340 m_aOldVersionItemsHashMap.clear();
341 m_aNewVersionItemsHashMap.clear();
342 }
343
344 // execute the migration items from Setup.xcu
345 copyConfig();
346
347 // execute custom migration services from Setup.xcu
348 // and refresh the cache
349 runServices();
350 refresh();
351
352 result = sal_True;
353 } catch (...)
354 {
355 OString aMsg("An unexpected exception was thrown during migration");
356 aMsg += "\nOldVersion: " + OUStringToOString(m_aInfo.productname, RTL_TEXTENCODING_ASCII_US);
357 aMsg += "\nDataPath : " + OUStringToOString(m_aInfo.userdata, RTL_TEXTENCODING_ASCII_US);
358 OSL_ENSURE(sal_False, aMsg.getStr());
359 }
360
361 // prevent running the migration multiple times
362 setMigrationCompleted();
363 return result;
364 }
365
refresh()366 void MigrationImpl::refresh()
367 {
368 uno::Reference< XRefreshable > xRefresh(m_xFactory->createInstance(
369 OUString::createFromAscii("com.sun.star.configuration.ConfigurationProvider")), uno::UNO_QUERY);
370 if (xRefresh.is())
371 xRefresh->refresh();
372 else
373 OSL_ENSURE(sal_False, "could not get XRefresh interface from default config provider. No refresh done.");
374
375 }
376
setMigrationCompleted()377 void MigrationImpl::setMigrationCompleted()
378 {
379 try {
380 uno::Reference< XPropertySet > aPropertySet(getConfigAccess("org.openoffice.Setup/Office", true), uno::UNO_QUERY_THROW);
381 aPropertySet->setPropertyValue(OUString::createFromAscii("MigrationCompleted"), uno::makeAny(sal_True));
382 uno::Reference< XChangesBatch >(aPropertySet, uno::UNO_QUERY_THROW)->commitChanges();
383 } catch (...) {
384 // fail silently
385 }
386 }
387
checkMigrationCompleted()388 sal_Bool MigrationImpl::checkMigrationCompleted()
389 {
390 sal_Bool bMigrationCompleted = sal_False;
391 try {
392 uno::Reference< XPropertySet > aPropertySet(
393 getConfigAccess("org.openoffice.Setup/Office"), uno::UNO_QUERY_THROW);
394 aPropertySet->getPropertyValue(
395 OUString::createFromAscii("MigrationCompleted")) >>= bMigrationCompleted;
396 } catch (Exception&) {
397 // just return false...
398 }
399 return bMigrationCompleted;
400 }
401
insertSorted(migrations_available & rAvailableMigrations,supported_migration & aSupportedMigration)402 static void insertSorted(migrations_available& rAvailableMigrations, supported_migration& aSupportedMigration)
403 {
404 bool bInserted( false );
405 migrations_available::iterator pIter = rAvailableMigrations.begin();
406 while ( !bInserted && pIter != rAvailableMigrations.end())
407 {
408 if ( pIter->nPriority < aSupportedMigration.nPriority )
409 {
410 rAvailableMigrations.insert(pIter, aSupportedMigration );
411 bInserted = true;
412 break; // i111193: insert invalidates iterator!
413 }
414 ++pIter;
415 }
416 if ( !bInserted )
417 rAvailableMigrations.push_back( aSupportedMigration );
418 }
419
readAvailableMigrations(migrations_available & rAvailableMigrations)420 bool MigrationImpl::readAvailableMigrations(migrations_available& rAvailableMigrations)
421 {
422 // get supported version names
423 uno::Reference< XNameAccess > aMigrationAccess(getConfigAccess("org.openoffice.Setup/Migration/SupportedVersions"), uno::UNO_QUERY_THROW);
424 uno::Sequence< OUString > seqSupportedVersions = aMigrationAccess->getElementNames();
425
426 const OUString aVersionIdentifiers( RTL_CONSTASCII_USTRINGPARAM( "VersionIdentifiers" ));
427 const OUString aPriorityIdentifier( RTL_CONSTASCII_USTRINGPARAM( "Priority" ));
428
429 for (sal_Int32 i=0; i<seqSupportedVersions.getLength(); i++)
430 {
431 sal_Int32 nPriority( 0 );
432 uno::Sequence< OUString > seqVersions;
433 uno::Reference< XNameAccess > xMigrationData( aMigrationAccess->getByName(seqSupportedVersions[i]), uno::UNO_QUERY_THROW );
434 xMigrationData->getByName( aVersionIdentifiers ) >>= seqVersions;
435 xMigrationData->getByName( aPriorityIdentifier ) >>= nPriority;
436
437 supported_migration aSupportedMigration;
438 aSupportedMigration.name = seqSupportedVersions[i];
439 aSupportedMigration.nPriority = nPriority;
440 for (sal_Int32 j=0; j<seqVersions.getLength(); j++)
441 aSupportedMigration.supported_versions.push_back(seqVersions[j].trim());
442 insertSorted( rAvailableMigrations, aSupportedMigration );
443 }
444
445 return true;
446 }
447
readMigrationSteps(const::rtl::OUString & rMigrationName)448 migrations_vr MigrationImpl::readMigrationSteps(const ::rtl::OUString& rMigrationName)
449 {
450 // get migration access
451 uno::Reference< XNameAccess > aMigrationAccess(getConfigAccess("org.openoffice.Setup/Migration/SupportedVersions"), uno::UNO_QUERY_THROW);
452 uno::Reference< XNameAccess > xMigrationData( aMigrationAccess->getByName(rMigrationName), uno::UNO_QUERY_THROW );
453
454 // get migration description from from org.openoffice.Setup/Migration
455 // and build vector of migration steps
456 OUString aMigrationSteps( RTL_CONSTASCII_USTRINGPARAM( "MigrationSteps" ));
457 uno::Reference< XNameAccess > theNameAccess(xMigrationData->getByName(aMigrationSteps), uno::UNO_QUERY_THROW);
458 uno::Sequence< OUString > seqMigrations = theNameAccess->getElementNames();
459 uno::Reference< XNameAccess > tmpAccess;
460 uno::Reference< XNameAccess > tmpAccess2;
461 uno::Sequence< OUString > tmpSeq;
462 migrations_vr vrMigrations(new migrations_v);
463 for (sal_Int32 i = 0; i < seqMigrations.getLength(); i++)
464 {
465 // get current migration step
466 theNameAccess->getByName(seqMigrations[i]) >>= tmpAccess;
467 // tmpStepPtr = new migration_step();
468 migration_step tmpStep;
469 tmpStep.name = seqMigrations[i];
470
471 // read included files from current step description
472 ::rtl::OUString aSeqEntry;
473 if (tmpAccess->getByName(OUString::createFromAscii("IncludedFiles")) >>= tmpSeq)
474 {
475 for (sal_Int32 j=0; j<tmpSeq.getLength(); j++)
476 {
477 aSeqEntry = tmpSeq[j];
478 tmpStep.includeFiles.push_back(aSeqEntry);
479 }
480 }
481
482 // exluded files...
483 if (tmpAccess->getByName(OUString::createFromAscii("ExcludedFiles")) >>= tmpSeq)
484 {
485 for (sal_Int32 j=0; j<tmpSeq.getLength(); j++)
486 tmpStep.excludeFiles.push_back(tmpSeq[j]);
487 }
488
489 // included nodes...
490 if (tmpAccess->getByName(OUString::createFromAscii("IncludedNodes")) >>= tmpSeq)
491 {
492 for (sal_Int32 j=0; j<tmpSeq.getLength(); j++)
493 tmpStep.includeConfig.push_back(tmpSeq[j]);
494 }
495
496 // excluded nodes...
497 if (tmpAccess->getByName(OUString::createFromAscii("ExcludedNodes")) >>= tmpSeq)
498 {
499 for (sal_Int32 j=0; j<tmpSeq.getLength(); j++)
500 tmpStep.excludeConfig.push_back(tmpSeq[j]);
501 }
502
503 // included extensions...
504 if (tmpAccess->getByName(OUString::createFromAscii("IncludedExtensions")) >>= tmpSeq)
505 {
506 for (sal_Int32 j=0; j<tmpSeq.getLength(); j++)
507 tmpStep.includeExtensions.push_back(tmpSeq[j]);
508 }
509
510 // excluded extensions...
511 if (tmpAccess->getByName(OUString::createFromAscii("ExcludedExtensions")) >>= tmpSeq)
512 {
513 for (sal_Int32 j=0; j<tmpSeq.getLength(); j++)
514 {
515 aSeqEntry = tmpSeq[j];
516 tmpStep.excludeExtensions.push_back(aSeqEntry);
517 }
518 }
519
520 // generic service
521 tmpAccess->getByName(OUString::createFromAscii("MigrationService")) >>= tmpStep.service;
522
523 vrMigrations->push_back(tmpStep);
524 }
525 return vrMigrations;
526 }
527
_checkAndCreateDirectory(INetURLObject & dirURL)528 static FileBase::RC _checkAndCreateDirectory(INetURLObject& dirURL)
529 {
530 FileBase::RC result = Directory::create(dirURL.GetMainURL(INetURLObject::DECODE_TO_IURI));
531 if (result == FileBase::E_NOENT)
532 {
533 INetURLObject baseURL(dirURL);
534 baseURL.removeSegment();
535 _checkAndCreateDirectory(baseURL);
536 return Directory::create(dirURL.GetMainURL(INetURLObject::DECODE_TO_IURI));
537 } else
538 return result;
539 }
540
findInstallation(const strings_v & rVersions)541 install_info MigrationImpl::findInstallation(const strings_v& rVersions)
542 {
543 rtl::OUString aProductName;
544 uno::Any aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTNAME );
545 aRet >>= aProductName;
546 aProductName = aProductName.toAsciiLowerCase();
547
548 install_info aInfo;
549 strings_v::const_iterator i_ver = rVersions.begin();
550 uno::Reference < util::XStringSubstitution > xSubst( ::comphelper::getProcessServiceFactory()->createInstance(::rtl::OUString::createFromAscii("com.sun.star.util.PathSubstitution")), uno::UNO_QUERY );
551 while (i_ver != rVersions.end())
552 {
553 ::rtl::OUString aVersion, aProfileName;
554 sal_Int32 nSeparatorIndex = (*i_ver).indexOf('=');
555 if ( nSeparatorIndex != -1 )
556 {
557 aVersion = (*i_ver).copy( 0, nSeparatorIndex );
558 aProfileName = (*i_ver).copy( nSeparatorIndex+1 );
559 }
560
561 if ( aVersion.getLength() && aProfileName.getLength() &&
562 ( !aInfo.userdata.getLength() || !aProfileName.toAsciiLowerCase().compareTo( aProductName, aProductName.getLength() ) )
563 )
564 {
565 ::rtl::OUString aUserInst;
566 osl::Security().getConfigDir( aUserInst );
567 if ( aUserInst.getLength() && aUserInst[ aUserInst.getLength()-1 ] != '/' )
568 aUserInst += ::rtl::OUString::createFromAscii("/");
569 #if defined UNX && ! defined MACOSX
570 // tribute to whoever had the "great" idea to use different names on Windows and Unix
571 aUserInst += ::rtl::OUString::createFromAscii(".");
572 #endif
573 aUserInst += aProfileName;
574 try
575 {
576 INetURLObject aObj(aUserInst);
577 ::ucbhelper::Content aCnt( aObj.GetMainURL( INetURLObject::NO_DECODE ), uno::Reference< ucb::XCommandEnvironment > () );
578 aCnt.isDocument();
579 aInfo.userdata = aObj.GetMainURL( INetURLObject::NO_DECODE );
580 aInfo.productname = aVersion;
581 }
582 catch( uno::Exception& ){}
583 }
584 ++i_ver;
585 }
586
587 return aInfo;
588 }
589
findPreferedMigrationProcess(const migrations_available & rAvailableMigrations)590 sal_Int32 MigrationImpl::findPreferedMigrationProcess(const migrations_available& rAvailableMigrations)
591 {
592 sal_Int32 nIndex( -1 );
593 sal_Int32 i( 0 );
594
595 migrations_available::const_iterator rIter = rAvailableMigrations.begin();
596 while ( rIter != rAvailableMigrations.end() )
597 {
598 install_info aInstallInfo = findInstallation(rIter->supported_versions);
599 if (aInstallInfo.productname.getLength() > 0 )
600 {
601 m_aInfo = aInstallInfo;
602 nIndex = i;
603 break;
604 }
605 ++i;
606 ++rIter;
607 }
608
609 return nIndex;
610 }
611
applyPatterns(const strings_v & vSet,const strings_v & vPatterns) const612 strings_vr MigrationImpl::applyPatterns(const strings_v& vSet, const strings_v& vPatterns) const
613 {
614 using namespace utl;
615 strings_vr vrResult(new strings_v);
616 strings_v::const_iterator i_set;
617 strings_v::const_iterator i_pat = vPatterns.begin();
618 while (i_pat != vPatterns.end())
619 {
620 // find matches for this pattern in input set
621 // and copy them to the result
622 SearchParam param(*i_pat, SearchParam::SRCH_REGEXP);
623 TextSearch ts(param, LANGUAGE_DONTKNOW);
624 i_set = vSet.begin();
625 xub_StrLen start = 0;
626 xub_StrLen end = 0;
627 while (i_set != vSet.end())
628 {
629 end = (xub_StrLen)(i_set->getLength());
630 if (ts.SearchFrwrd(*i_set, &start, &end))
631 vrResult->push_back(*i_set);
632 i_set++;
633 }
634 i_pat++;
635 }
636 return vrResult;
637 }
638
getAllFiles(const OUString & baseURL) const639 strings_vr MigrationImpl::getAllFiles(const OUString& baseURL) const
640 {
641 using namespace osl;
642 strings_vr vrResult(new strings_v);
643
644 // get sub dirs
645 Directory dir(baseURL);
646 if (dir.open() == FileBase::E_None)
647 {
648 strings_v vSubDirs;
649 strings_vr vrSubResult;
650
651 // work through directory contents...
652 DirectoryItem item;
653 FileStatus fs(FileStatusMask_Type | FileStatusMask_FileURL);
654 while (dir.getNextItem(item) == FileBase::E_None)
655 {
656 if (item.getFileStatus(fs) == FileBase::E_None)
657 {
658 if (fs.getFileType() == FileStatus::Directory)
659 vSubDirs.push_back(fs.getFileURL());
660 else
661 vrResult->push_back(fs.getFileURL());
662 }
663 }
664
665 // recurse subfolders
666 strings_v::const_iterator i = vSubDirs.begin();
667 while (i != vSubDirs.end())
668 {
669 vrSubResult = getAllFiles(*i);
670 vrResult->insert(vrResult->end(), vrSubResult->begin(), vrSubResult->end());
671 i++;
672 }
673 }
674 return vrResult;
675 }
676
compileFileList()677 strings_vr MigrationImpl::compileFileList()
678 {
679
680 strings_vr vrResult(new strings_v);
681 strings_vr vrInclude;
682 strings_vr vrExclude;
683 strings_vr vrTemp;
684
685 #ifdef SAL_OS2
686 if (m_aInfo.userdata.getLength() == 0)
687 return vrResult;
688 #endif
689
690 // get a list of all files:
691 strings_vr vrFiles = getAllFiles(m_aInfo.userdata);
692
693 // get a file list result for each migration step
694 migrations_v::const_iterator i_migr = m_vrMigrations->begin();
695 while (i_migr != m_vrMigrations->end())
696 {
697 vrInclude = applyPatterns(*vrFiles, i_migr->includeFiles);
698 vrExclude = applyPatterns(*vrFiles, i_migr->excludeFiles);
699 substract(*vrInclude, *vrExclude);
700 vrResult->insert(vrResult->end(), vrInclude->begin(), vrInclude->end());
701 i_migr++;
702 }
703 return vrResult;
704 }
705
706 namespace {
707
708 struct componentParts {
709 std::set< rtl::OUString > includedPaths;
710 std::set< rtl::OUString > excludedPaths;
711 };
712
713 typedef std::map< rtl::OUString, componentParts > Components;
714
getComponent(rtl::OUString const & path,rtl::OUString * component)715 bool getComponent(rtl::OUString const & path, rtl::OUString * component) {
716 OSL_ASSERT(component != 0);
717 if (path.getLength() == 0 || path[0] != '/') {
718 OSL_TRACE(
719 ("configuration migration in/exclude path %s ignored (does not"
720 " start with slash)"),
721 rtl::OUStringToOString(path, RTL_TEXTENCODING_UTF8).getStr());
722 return false;
723 }
724 sal_Int32 i = path.indexOf('/', 1);
725 *component = i < 0 ? path.copy(1) : path.copy(1, i - 1);
726 return true;
727 }
728
setToSeq(std::set<rtl::OUString> const & set)729 uno::Sequence< rtl::OUString > setToSeq(std::set< rtl::OUString > const & set) {
730 std::set< rtl::OUString >::size_type n = set.size();
731 if (n > SAL_MAX_INT32) {
732 throw std::bad_alloc();
733 }
734 uno::Sequence< rtl::OUString > seq(static_cast< sal_Int32 >(n));
735 sal_Int32 i = 0;
736 for (std::set< rtl::OUString >::const_iterator j(set.begin());
737 j != set.end(); ++j)
738 {
739 seq[i++] = *j;
740 }
741 return seq;
742 }
743
744 }
745
copyConfig()746 void MigrationImpl::copyConfig() {
747 Components comps;
748 for (migrations_v::const_iterator i(m_vrMigrations->begin());
749 i != m_vrMigrations->end(); ++i)
750 {
751 for (strings_v::const_iterator j(i->includeConfig.begin());
752 j != i->includeConfig.end(); ++j)
753 {
754 rtl::OUString comp;
755 if (getComponent(*j, &comp)) {
756 comps[comp].includedPaths.insert(*j);
757 }
758 }
759 for (strings_v::const_iterator j(i->excludeConfig.begin());
760 j != i->excludeConfig.end(); ++j)
761 {
762 rtl::OUString comp;
763 if (getComponent(*j, &comp)) {
764 comps[comp].excludedPaths.insert(*j);
765 }
766 }
767 }
768 for (Components::const_iterator i(comps.begin()); i != comps.end(); ++i) {
769 if (!i->second.includedPaths.empty()) {
770 rtl::OUStringBuffer buf(m_aInfo.userdata);
771 if ( m_aInfo.productname.equals( OUString::createFromAscii("OpenOffice.org 3") ) )
772 {
773 // OpenOffice.org 3 configuration file
774 buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("/user/registrymodifications.xcu"));
775 }
776 else
777 {
778 // OpenOffice.org 2 configuration files
779 buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("/user/registry/data"));
780 sal_Int32 n = 0;
781 do {
782 rtl::OUString seg(i->first.getToken(0, '.', n));
783 rtl::OUString enc(
784 rtl::Uri::encode(
785 seg, rtl_UriCharClassPchar, rtl_UriEncodeStrict,
786 RTL_TEXTENCODING_UTF8));
787 if (enc.getLength() == 0 && seg.getLength() != 0) {
788 OSL_TRACE(
789 ("configuration migration component %s ignored (cannot"
790 " be encoded as file path)"),
791 rtl::OUStringToOString(
792 i->first, RTL_TEXTENCODING_UTF8).getStr());
793 goto next;
794 }
795 buf.append(sal_Unicode('/'));
796 buf.append(enc);
797 } while (n >= 0);
798 buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(".xcu"));
799 }
800 configuration::Update::get(
801 comphelper::getProcessComponentContext())->
802 insertModificationXcuFile(
803 buf.makeStringAndClear(), setToSeq(i->second.includedPaths),
804 setToSeq(i->second.excludedPaths));
805 } else {
806 OSL_TRACE(
807 ("configuration migration component %s ignored (only excludes,"
808 " no includes)"),
809 rtl::OUStringToOString(
810 i->first, RTL_TEXTENCODING_UTF8).getStr());
811 }
812 next:;
813 }
814 }
815
816 // removes elements of vector 2 in vector 1
substract(strings_v & va,const strings_v & vb_c) const817 void MigrationImpl::substract(strings_v& va, const strings_v& vb_c) const
818 {
819 strings_v vb(vb_c);
820 // ensure uniqueness of entries
821 sort(va.begin(), va.end());
822 sort(vb.begin(), vb.end());
823 unique(va.begin(), va.end());
824 unique(vb.begin(), vb.end());
825
826 strings_v::const_iterator i_ex = vb.begin();
827 strings_v::iterator i_in;
828 strings_v::iterator i_next;
829 while (i_ex != vb.end())
830 {
831 i_in = va.begin();
832 while (i_in != va.end())
833 {
834 if ( *i_in == *i_ex)
835 {
836 i_next = i_in+1;
837 va.erase(i_in);
838 i_in = i_next;
839 // we can only find one match since we
840 // ensured uniquness of the entries. ergo:
841 break;
842 }
843 else
844 i_in++;
845 }
846 i_ex++;
847 }
848 }
849
getConfigAccess(const sal_Char * pPath,sal_Bool bUpdate)850 uno::Reference< XNameAccess > MigrationImpl::getConfigAccess(const sal_Char* pPath, sal_Bool bUpdate)
851 {
852 uno::Reference< XNameAccess > xNameAccess;
853 try{
854 OUString sConfigSrvc = OUString::createFromAscii("com.sun.star.configuration.ConfigurationProvider");
855 OUString sAccessSrvc;
856 if (bUpdate)
857 sAccessSrvc = OUString::createFromAscii("com.sun.star.configuration.ConfigurationUpdateAccess");
858 else
859 sAccessSrvc = OUString::createFromAscii("com.sun.star.configuration.ConfigurationAccess");
860
861 OUString sConfigURL = OUString::createFromAscii(pPath);
862
863 // get configuration provider
864 uno::Reference< XMultiServiceFactory > theMSF = comphelper::getProcessServiceFactory();
865 uno::Reference< XMultiServiceFactory > theConfigProvider = uno::Reference< XMultiServiceFactory > (
866 theMSF->createInstance( sConfigSrvc ),uno::UNO_QUERY_THROW );
867
868 // access the provider
869 uno::Sequence< uno::Any > theArgs(1);
870 theArgs[ 0 ] <<= sConfigURL;
871 xNameAccess = uno::Reference< XNameAccess > (
872 theConfigProvider->createInstanceWithArguments(
873 sAccessSrvc, theArgs ), uno::UNO_QUERY_THROW );
874 } catch (com::sun::star::uno::Exception& e)
875 {
876 OString aMsg = OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US);
877 OSL_ENSURE(sal_False, aMsg.getStr());
878 }
879 return xNameAccess;
880 }
881
copyFiles()882 void MigrationImpl::copyFiles()
883 {
884 strings_v::const_iterator i_file = m_vrFileList->begin();
885 OUString localName;
886 OUString destName;
887 OUString userInstall;
888 utl::Bootstrap::PathStatus aStatus;
889 aStatus = utl::Bootstrap::locateUserInstallation(userInstall);
890 if (aStatus == utl::Bootstrap::PATH_EXISTS)
891 {
892 while (i_file != m_vrFileList->end())
893 {
894
895 // remove installation prefix from file
896 localName = i_file->copy(m_aInfo.userdata.getLength());
897 destName = userInstall + localName;
898 INetURLObject aURL(destName);
899 // check whether destination directory exists
900 aURL.removeSegment();
901 _checkAndCreateDirectory(aURL);
902 FileBase::RC copyResult = File::copy(*i_file, destName);
903 if (copyResult != FileBase::E_None)
904 {
905 OString msg("Cannot copy ");
906 msg += OUStringToOString(*i_file, RTL_TEXTENCODING_UTF8) + " to "
907 + OUStringToOString(destName, RTL_TEXTENCODING_UTF8);
908 OSL_ENSURE(sal_False, msg.getStr());
909 }
910 i_file++;
911 }
912 }
913 else
914 {
915 OSL_ENSURE(sal_False, "copyFiles: UserInstall does not exist");
916 }
917 }
918
runServices()919 void MigrationImpl::runServices()
920 {
921 // Build argument array
922 uno::Sequence< uno::Any > seqArguments(3);
923 seqArguments[0] = uno::makeAny(NamedValue(
924 OUString::createFromAscii("Productname"),
925 uno::makeAny(m_aInfo.productname)));
926 seqArguments[1] = uno::makeAny(NamedValue(
927 OUString::createFromAscii("UserData"),
928 uno::makeAny(m_aInfo.userdata)));
929
930
931 // create an instance of every migration service
932 // and execute the migration job
933 uno::Reference< XJob > xMigrationJob;
934
935 migrations_v::const_iterator i_mig = m_vrMigrations->begin();
936 while (i_mig != m_vrMigrations->end())
937 {
938 if( i_mig->service.getLength() > 0)
939 {
940
941 try
942 {
943 // set black list for extension migration
944 uno::Sequence< rtl::OUString > seqExtBlackList;
945 sal_uInt32 nSize = i_mig->excludeExtensions.size();
946 if ( nSize > 0 )
947 seqExtBlackList = comphelper::arrayToSequence< ::rtl::OUString >(
948 &i_mig->excludeExtensions[0], nSize );
949 seqArguments[2] = uno::makeAny(NamedValue(
950 OUString::createFromAscii("ExtensionBlackList"),
951 uno::makeAny( seqExtBlackList )));
952
953 xMigrationJob = uno::Reference< XJob >(m_xFactory->createInstanceWithArguments(
954 i_mig->service, seqArguments), uno::UNO_QUERY_THROW);
955
956 xMigrationJob->execute(uno::Sequence< NamedValue >());
957
958
959 } catch (Exception& e)
960 {
961 OString aMsg("Execution of migration service failed (Exception caught).\nService: ");
962 aMsg += OUStringToOString(i_mig->service, RTL_TEXTENCODING_ASCII_US) + "\nMessage: ";
963 aMsg += OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US);
964 OSL_ENSURE(sal_False, aMsg.getStr());
965 } catch (...)
966 {
967 OString aMsg("Execution of migration service failed (Exception caught).\nService: ");
968 aMsg += OUStringToOString(i_mig->service, RTL_TEXTENCODING_ASCII_US) +
969 "\nNo message available";
970 OSL_ENSURE(sal_False, aMsg.getStr());
971 }
972
973 }
974 i_mig++;
975 }
976 }
977
dectectUIChangesForAllModules() const978 ::std::vector< MigrationModuleInfo > MigrationImpl::dectectUIChangesForAllModules() const
979 {
980 ::std::vector< MigrationModuleInfo > vModulesInfo;
981 const ::rtl::OUString MENUBAR = ::rtl::OUString::createFromAscii("menubar");
982 const ::rtl::OUString TOOLBAR = ::rtl::OUString::createFromAscii("toolbar");
983
984 uno::Sequence< uno::Any > lArgs(2);
985 lArgs[0] <<= m_aInfo.userdata + ::rtl::OUString::createFromAscii("/user/config/soffice.cfg/modules");
986 lArgs[1] <<= embed::ElementModes::READ;
987
988 uno::Reference< lang::XSingleServiceFactory > xStorageFactory(m_xFactory->createInstance(::rtl::OUString::createFromAscii("com.sun.star.embed.FileSystemStorageFactory")), uno::UNO_QUERY);
989 uno::Reference< embed::XStorage > xModules;
990
991 xModules = uno::Reference< embed::XStorage >(xStorageFactory->createInstanceWithArguments(lArgs), uno::UNO_QUERY);
992 if (!xModules.is())
993 return vModulesInfo;
994
995 uno::Reference< container::XNameAccess > xAccess = uno::Reference< container::XNameAccess >(xModules, uno::UNO_QUERY);
996 uno::Sequence< ::rtl::OUString > lNames = xAccess->getElementNames();
997 sal_Int32 nLength = lNames.getLength();
998 for (sal_Int32 i=0; i<nLength; ++i)
999 {
1000 ::rtl::OUString sModuleShortName = lNames[i];
1001 uno::Reference< embed::XStorage > xModule = xModules->openStorageElement(sModuleShortName, embed::ElementModes::READ);
1002 if (xModule.is())
1003 {
1004 MigrationModuleInfo aModuleInfo;
1005
1006 uno::Reference< embed::XStorage > xMenubar = xModule->openStorageElement(MENUBAR, embed::ElementModes::READ);
1007 if (xMenubar.is())
1008 {
1009 uno::Reference< container::XNameAccess > xNameAccess = uno::Reference< container::XNameAccess >(xMenubar, uno::UNO_QUERY);
1010 if (xNameAccess->getElementNames().getLength() > 0)
1011 {
1012 aModuleInfo.sModuleShortName = sModuleShortName;
1013 aModuleInfo.bHasMenubar = sal_True;
1014 }
1015 }
1016
1017 uno::Reference< embed::XStorage > xToolbar = xModule->openStorageElement(TOOLBAR, embed::ElementModes::READ);
1018 if (xToolbar.is())
1019 {
1020 const ::rtl::OUString RESOURCEURL_CUSTOM_ELEMENT = ::rtl::OUString::createFromAscii("custom_");
1021 sal_Int32 nCustomLen = 7;
1022
1023 uno::Reference< container::XNameAccess > xNameAccess = uno::Reference< container::XNameAccess >(xToolbar, uno::UNO_QUERY);
1024 ::uno::Sequence< ::rtl::OUString > lToolbars = xNameAccess->getElementNames();
1025 for (sal_Int32 j=0; j<lToolbars.getLength(); ++j)
1026 {
1027 ::rtl::OUString sToolbarName = lToolbars[j];
1028 if (sToolbarName.getLength()>=nCustomLen &&
1029 sToolbarName.copy(0, nCustomLen).equals(RESOURCEURL_CUSTOM_ELEMENT))
1030 continue;
1031
1032 aModuleInfo.sModuleShortName = sModuleShortName;
1033 sal_Int32 nIndex = sToolbarName.lastIndexOf('.');
1034 if (nIndex > 0)
1035 {
1036 ::rtl::OUString sExtension(sToolbarName.copy(nIndex));
1037 ::rtl::OUString sToolbarResourceName(sToolbarName.copy(0, nIndex));
1038 if (sToolbarResourceName.getLength()>0 && sExtension.equalsAsciiL(".xml", 4))
1039 aModuleInfo.m_vToolbars.push_back(sToolbarResourceName);
1040 }
1041 }
1042 }
1043
1044 if (aModuleInfo.sModuleShortName.getLength()>0)
1045 vModulesInfo.push_back(aModuleInfo);
1046 }
1047 }
1048
1049 return vModulesInfo;
1050 }
1051
compareOldAndNewConfig(const::rtl::OUString & sParent,const uno::Reference<container::XIndexContainer> & xIndexOld,const uno::Reference<container::XIndexContainer> & xIndexNew,const::rtl::OUString & sResourceURL)1052 void MigrationImpl::compareOldAndNewConfig(const ::rtl::OUString& sParent,
1053 const uno::Reference< container::XIndexContainer >& xIndexOld,
1054 const uno::Reference< container::XIndexContainer >& xIndexNew,
1055 const ::rtl::OUString& sResourceURL)
1056 {
1057 ::std::vector< MigrationItem > vOldItems;
1058 ::std::vector< MigrationItem > vNewItems;
1059 uno::Sequence< beans::PropertyValue > aProp;
1060 sal_Int32 nOldCount = xIndexOld->getCount();
1061 sal_Int32 nNewCount = xIndexNew->getCount();
1062
1063 for (int n=0; n<nOldCount; ++n)
1064 {
1065 MigrationItem aMigrationItem;
1066 if (xIndexOld->getByIndex(n) >>= aProp)
1067 {
1068 for(int i=0; i<aProp.getLength(); ++i)
1069 {
1070 if (aProp[i].Name.equals(ITEM_DESCRIPTOR_COMMANDURL))
1071 aProp[i].Value >>= aMigrationItem.m_sCommandURL;
1072 else if (aProp[i].Name.equals(ITEM_DESCRIPTOR_CONTAINER))
1073 aProp[i].Value >>= aMigrationItem.m_xPopupMenu;
1074 }
1075
1076 if (aMigrationItem.m_sCommandURL.getLength())
1077 vOldItems.push_back(aMigrationItem);
1078 }
1079 }
1080
1081 for (int n=0; n<nNewCount; ++n)
1082 {
1083 MigrationItem aMigrationItem;
1084 if (xIndexNew->getByIndex(n) >>= aProp)
1085 {
1086 for(int i=0; i<aProp.getLength(); ++i)
1087 {
1088 if (aProp[i].Name.equals(ITEM_DESCRIPTOR_COMMANDURL))
1089 aProp[i].Value >>= aMigrationItem.m_sCommandURL;
1090 else if (aProp[i].Name.equals(ITEM_DESCRIPTOR_CONTAINER))
1091 aProp[i].Value >>= aMigrationItem.m_xPopupMenu;
1092 }
1093
1094 if (aMigrationItem.m_sCommandURL.getLength())
1095 vNewItems.push_back(aMigrationItem);
1096 }
1097 }
1098
1099 ::std::vector< MigrationItem >::iterator it;
1100
1101 ::rtl::OUString sSibling;
1102 for (it = vOldItems.begin(); it!=vOldItems.end(); ++it)
1103 {
1104 ::std::vector< MigrationItem >::iterator pFound = ::std::find(vNewItems.begin(), vNewItems.end(), *it);
1105 if (pFound != vNewItems.end() && it->m_xPopupMenu.is())
1106 {
1107 ::rtl::OUString sName;
1108 if (sParent.getLength()>0)
1109 sName = sParent + MENU_SEPERATOR + it->m_sCommandURL;
1110 else
1111 sName = it->m_sCommandURL;
1112 compareOldAndNewConfig(sName, it->m_xPopupMenu, pFound->m_xPopupMenu, sResourceURL);
1113 }
1114 else if (pFound == vNewItems.end())
1115 {
1116 MigrationItem aMigrationItem(sParent, sSibling, it->m_sCommandURL, it->m_xPopupMenu);
1117 if (m_aOldVersionItemsHashMap.find(sResourceURL)==m_aOldVersionItemsHashMap.end())
1118 {
1119 ::std::vector< MigrationItem > vMigrationItems;
1120 m_aOldVersionItemsHashMap.insert(MigrationHashMap::value_type(sResourceURL, vMigrationItems));
1121 m_aOldVersionItemsHashMap[sResourceURL].push_back(aMigrationItem);
1122 }
1123 else
1124 {
1125 if (::std::find(m_aOldVersionItemsHashMap[sResourceURL].begin(), m_aOldVersionItemsHashMap[sResourceURL].end(), aMigrationItem)==m_aOldVersionItemsHashMap[sResourceURL].end())
1126 m_aOldVersionItemsHashMap[sResourceURL].push_back(aMigrationItem);
1127 }
1128 }
1129
1130 sSibling = it->m_sCommandURL;
1131 }
1132
1133 ::rtl::OUString sNewSibling;
1134 uno::Reference< container::XIndexContainer > xPopup;
1135 for (it = vNewItems.begin(); it!=vNewItems.end(); ++it)
1136 {
1137 ::std::vector< MigrationItem >::iterator pFound = ::std::find(vOldItems.begin(), vOldItems.end(), *it);
1138 if (pFound != vOldItems.end() && it->m_xPopupMenu.is())
1139 {
1140 ::rtl::OUString sName;
1141 if (sParent.getLength()>0)
1142 sName = sParent + MENU_SEPERATOR + it->m_sCommandURL;
1143 else
1144 sName = it->m_sCommandURL;
1145 compareOldAndNewConfig(sName, pFound->m_xPopupMenu, it->m_xPopupMenu, sResourceURL);
1146 }
1147 else if (::std::find(vOldItems.begin(), vOldItems.end(), *it) == vOldItems.end())
1148 {
1149 MigrationItem aMigrationItem(sParent, sSibling, it->m_sCommandURL, it->m_xPopupMenu);
1150 if (m_aNewVersionItemsHashMap.find(sResourceURL)==m_aNewVersionItemsHashMap.end())
1151 {
1152 ::std::vector< MigrationItem > vMigrationItems;
1153 m_aNewVersionItemsHashMap.insert(MigrationHashMap::value_type(sResourceURL, vMigrationItems));
1154 m_aNewVersionItemsHashMap[sResourceURL].push_back(aMigrationItem);
1155 }
1156 else
1157 {
1158 if (::std::find(m_aNewVersionItemsHashMap[sResourceURL].begin(), m_aNewVersionItemsHashMap[sResourceURL].end(), aMigrationItem)==m_aNewVersionItemsHashMap[sResourceURL].end())
1159 m_aNewVersionItemsHashMap[sResourceURL].push_back(aMigrationItem);
1160 }
1161 }
1162 }
1163 }
1164
mergeOldToNewVersion(const uno::Reference<ui::XUIConfigurationManager> & xCfgManager,const uno::Reference<container::XIndexContainer> & xIndexContainer,const::rtl::OUString & sModuleIdentifier,const::rtl::OUString & sResourceURL)1165 void MigrationImpl::mergeOldToNewVersion(const uno::Reference< ui::XUIConfigurationManager >& xCfgManager,
1166 const uno::Reference< container::XIndexContainer>& xIndexContainer,
1167 const ::rtl::OUString& sModuleIdentifier,
1168 const ::rtl::OUString& sResourceURL)
1169 {
1170 MigrationHashMap::iterator pFound = m_aOldVersionItemsHashMap.find(sResourceURL);
1171 if (pFound==m_aOldVersionItemsHashMap.end())
1172 return;
1173
1174 ::std::vector< MigrationItem >::iterator it;
1175 for (it=pFound->second.begin(); it!=pFound->second.end(); ++it)
1176 {
1177 uno::Reference< container::XIndexContainer > xTemp = xIndexContainer;
1178
1179 ::rtl::OUString sParentNodeName = it->m_sParentNodeName;
1180 sal_Int32 nIndex = 0;
1181 do
1182 {
1183 ::rtl::OUString sToken = sParentNodeName.getToken(0, '|', nIndex).trim();
1184 if (sToken.getLength()<=0)
1185 break;
1186
1187 sal_Int32 nCount = xTemp->getCount();
1188 for (sal_Int32 i=0; i<nCount; ++i)
1189 {
1190 ::rtl::OUString sCommandURL;
1191 ::rtl::OUString sLabel;
1192 uno::Reference< container::XIndexContainer > xChild;
1193
1194 uno::Sequence< beans::PropertyValue > aPropSeq;
1195 xTemp->getByIndex(i) >>= aPropSeq;
1196 for (sal_Int32 j=0; j<aPropSeq.getLength(); ++j)
1197 {
1198 ::rtl::OUString sPropName = aPropSeq[j].Name;
1199 if (sPropName.equals(ITEM_DESCRIPTOR_COMMANDURL))
1200 aPropSeq[j].Value >>= sCommandURL;
1201 else if (sPropName.equals(ITEM_DESCRIPTOR_LABEL))
1202 aPropSeq[j].Value >>= sLabel;
1203 else if (sPropName.equals(ITEM_DESCRIPTOR_CONTAINER))
1204 aPropSeq[j].Value >>= xChild;
1205 }
1206
1207 if (sCommandURL == sToken)
1208 {
1209 xTemp = xChild;
1210 break;
1211 }
1212 }
1213
1214 } while (nIndex>=0);
1215
1216 if (nIndex == -1)
1217 {
1218 uno::Sequence< beans::PropertyValue > aPropSeq(3);
1219
1220 aPropSeq[0].Name = ITEM_DESCRIPTOR_COMMANDURL;
1221 aPropSeq[0].Value <<= it->m_sCommandURL;
1222 aPropSeq[1].Name = ITEM_DESCRIPTOR_LABEL;
1223 aPropSeq[1].Value <<= retrieveLabelFromCommand(it->m_sCommandURL, sModuleIdentifier);
1224 aPropSeq[2].Name = ITEM_DESCRIPTOR_CONTAINER;
1225 aPropSeq[2].Value <<= it->m_xPopupMenu;
1226
1227 if (it->m_sPrevSibling.getLength() == 0)
1228 xTemp->insertByIndex(0, uno::makeAny(aPropSeq));
1229 else if (it->m_sPrevSibling.getLength() > 0)
1230 {
1231 sal_Int32 nCount = xTemp->getCount();
1232 sal_Int32 i = 0;
1233 for (; i<nCount; ++i)
1234 {
1235 ::rtl::OUString sCmd;
1236 uno::Sequence< beans::PropertyValue > aTempPropSeq;
1237 xTemp->getByIndex(i) >>= aTempPropSeq;
1238 for (sal_Int32 j=0; j<aTempPropSeq.getLength(); ++j)
1239 {
1240 if (aTempPropSeq[j].Name.equals(ITEM_DESCRIPTOR_COMMANDURL))
1241 {
1242 aTempPropSeq[j].Value >>= sCmd;
1243 break;
1244 }
1245 }
1246
1247 if (sCmd.equals(it->m_sPrevSibling))
1248 break;
1249 }
1250
1251 xTemp->insertByIndex(i+1, uno::makeAny(aPropSeq));
1252 }
1253 }
1254 }
1255
1256 uno::Reference< container::XIndexAccess > xIndexAccess(xIndexContainer, uno::UNO_QUERY);
1257 if (xIndexAccess.is())
1258 xCfgManager->replaceSettings(sResourceURL, xIndexAccess);
1259
1260 uno::Reference< ui::XUIConfigurationPersistence > xUIConfigurationPersistence(xCfgManager, uno::UNO_QUERY);
1261 if (xUIConfigurationPersistence.is())
1262 xUIConfigurationPersistence->store();
1263 }
1264
getConfigManager(const::rtl::OUString & sModuleShortName) const1265 uno::Reference< ui::XUIConfigurationManager > NewVersionUIInfo::getConfigManager(const ::rtl::OUString& sModuleShortName) const
1266 {
1267 uno::Reference< ui::XUIConfigurationManager > xCfgManager;
1268
1269 for (sal_Int32 i=0; i<m_lCfgManagerSeq.getLength(); ++i)
1270 {
1271 if (m_lCfgManagerSeq[i].Name.equals(sModuleShortName))
1272 {
1273 m_lCfgManagerSeq[i].Value >>= xCfgManager;
1274 break;
1275 }
1276 }
1277
1278 return xCfgManager;
1279 }
1280
getNewMenubarSettings(const::rtl::OUString & sModuleShortName) const1281 uno::Reference< container::XIndexContainer > NewVersionUIInfo::getNewMenubarSettings(const ::rtl::OUString& sModuleShortName) const
1282 {
1283 uno::Reference< container::XIndexContainer > xNewMenuSettings;
1284
1285 for (sal_Int32 i=0; i<m_lNewVersionMenubarSettingsSeq.getLength(); ++i)
1286 {
1287 if (m_lNewVersionMenubarSettingsSeq[i].Name.equals(sModuleShortName))
1288 {
1289 m_lNewVersionMenubarSettingsSeq[i].Value >>= xNewMenuSettings;
1290 break;
1291 }
1292 }
1293
1294 return xNewMenuSettings;
1295 }
1296
getNewToolbarSettings(const::rtl::OUString & sModuleShortName,const::rtl::OUString & sToolbarName) const1297 uno::Reference< container::XIndexContainer > NewVersionUIInfo::getNewToolbarSettings(const ::rtl::OUString& sModuleShortName, const ::rtl::OUString& sToolbarName) const
1298 {
1299 uno::Reference< container::XIndexContainer > xNewToolbarSettings;
1300
1301 for (sal_Int32 i=0; i<m_lNewVersionToolbarSettingsSeq.getLength(); ++i)
1302 {
1303 if (m_lNewVersionToolbarSettingsSeq[i].Name.equals(sModuleShortName))
1304 {
1305 uno::Sequence< beans::PropertyValue > lToolbarSettingsSeq;
1306 m_lNewVersionToolbarSettingsSeq[i].Value >>= lToolbarSettingsSeq;
1307 for (sal_Int32 j=0; j<lToolbarSettingsSeq.getLength(); ++j)
1308 {
1309 if (lToolbarSettingsSeq[j].Name.equals(sToolbarName))
1310 {
1311 lToolbarSettingsSeq[j].Value >>= xNewToolbarSettings;
1312 break;
1313 }
1314 }
1315
1316 break;
1317 }
1318 }
1319
1320 return xNewToolbarSettings;
1321 }
1322
init(const::std::vector<MigrationModuleInfo> & vModulesInfo)1323 void NewVersionUIInfo::init(const ::std::vector< MigrationModuleInfo >& vModulesInfo)
1324 {
1325 m_lCfgManagerSeq.realloc(vModulesInfo.size());
1326 m_lNewVersionMenubarSettingsSeq.realloc(vModulesInfo.size());
1327 m_lNewVersionToolbarSettingsSeq.realloc(vModulesInfo.size());
1328
1329 const ::rtl::OUString sModuleCfgSupplier = ::rtl::OUString::createFromAscii("com.sun.star.ui.ModuleUIConfigurationManagerSupplier");
1330 const ::rtl::OUString sMenubarResourceURL = ::rtl::OUString::createFromAscii("private:resource/menubar/menubar");
1331 const ::rtl::OUString sToolbarResourcePre = ::rtl::OUString::createFromAscii("private:resource/toolbar/");
1332
1333 uno::Reference< ui::XModuleUIConfigurationManagerSupplier > xModuleCfgSupplier = uno::Reference< ui::XModuleUIConfigurationManagerSupplier >(::comphelper::getProcessServiceFactory()->createInstance(sModuleCfgSupplier), uno::UNO_QUERY);
1334
1335 for (sal_uInt32 i=0; i<vModulesInfo.size(); ++i)
1336 {
1337 ::rtl::OUString sModuleIdentifier = mapModuleShortNameToIdentifier(vModulesInfo[i].sModuleShortName);
1338 if (sModuleIdentifier.getLength() > 0)
1339 {
1340 uno::Reference< ui::XUIConfigurationManager > xCfgManager = xModuleCfgSupplier->getUIConfigurationManager(sModuleIdentifier);
1341 m_lCfgManagerSeq[i].Name = vModulesInfo[i].sModuleShortName;
1342 m_lCfgManagerSeq[i].Value <<= xCfgManager;
1343
1344 if (vModulesInfo[i].bHasMenubar)
1345 {
1346 m_lNewVersionMenubarSettingsSeq[i].Name = vModulesInfo[i].sModuleShortName;
1347 m_lNewVersionMenubarSettingsSeq[i].Value <<= xCfgManager->getSettings(sMenubarResourceURL, sal_True);
1348 }
1349
1350 sal_Int32 nToolbars = vModulesInfo[i].m_vToolbars.size();
1351 if (nToolbars > 0)
1352 {
1353 uno::Sequence< beans::PropertyValue > lPropSeq(nToolbars);
1354 for (sal_Int32 j=0; j<nToolbars; ++j)
1355 {
1356 ::rtl::OUString sToolbarName = vModulesInfo[i].m_vToolbars[j];
1357 ::rtl::OUString sToolbarResourceURL = sToolbarResourcePre + sToolbarName;
1358
1359 lPropSeq[j].Name = sToolbarName;
1360 lPropSeq[j].Value <<= xCfgManager->getSettings(sToolbarResourceURL, sal_True);
1361 }
1362
1363 m_lNewVersionToolbarSettingsSeq[i].Name = vModulesInfo[i].sModuleShortName;
1364 m_lNewVersionToolbarSettingsSeq[i].Value <<= lPropSeq;
1365 }
1366 }
1367 }
1368 }
1369
1370 } // namespace desktop
1371