xref: /AOO41X/main/desktop/source/migration/migration.cxx (revision d3e0dd8eb215533c15e891ee35bd141abe9397ee)
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