merge the formfield patch from ooo-build
[ooovba.git] / desktop / source / migration / services / extensionmigration.cxx
blobadf2038d8e1f8e8b296f3f4429ba238fadc2162b
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: extensionmigration.cxx,v $
10 * $Revision: 1.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_desktop.hxx"
33 #include "extensionmigration.hxx"
34 #include <tools/urlobj.hxx>
35 #include <unotools/bootstrap.hxx>
36 #include <unotools/ucbstreamhelper.hxx>
37 #include <ucbhelper/content.hxx>
38 #include <com/sun/star/ucb/XCommandInfo.hpp>
39 #include <com/sun/star/ucb/TransferInfo.hpp>
40 #include <com/sun/star/ucb/NameClash.hpp>
41 #include "comphelper/processfactory.hxx"
42 #include "com/sun/star/deployment/XPackageManagerFactory.hpp"
43 #include "com/sun/star/ucb/XCommandEnvironment.hpp"
44 #include "com/sun/star/xml/sax/XParser.hpp"
45 #include "rtl/instance.hxx"
46 #include "osl/file.hxx"
47 #include "osl/thread.h"
49 #include "xmlscript/xmllib_imexp.hxx"
50 #include "../../deployment/inc/dp_ucb.h"
52 #ifdef SYSTEM_DB
53 #include <db.h>
54 #else
55 #include <berkeleydb/db.h>
56 #endif
58 using namespace ::com::sun::star;
59 using namespace ::com::sun::star::uno;
61 namespace {
63 struct LibDescriptor :
64 public rtl::StaticWithInit<const ::xmlscript::LibDescriptorArray, LibDescriptor> {
65 const ::xmlscript::LibDescriptorArray operator () () {
68 return ::xmlscript::LibDescriptorArray();
72 //.........................................................................
73 namespace migration
75 //.........................................................................
78 static ::rtl::OUString sExtensionSubDir = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/user/uno_packages/" ) );
79 static ::rtl::OUString sSubDirName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cache" ) );
80 static ::rtl::OUString sConfigDir = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/user/registry/data" ) );
81 static ::rtl::OUString sOrgDir = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/user/registry/data/org" ) );
82 static ::rtl::OUString sExcludeDir1 = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/user/registry/data/org" ) );
83 static ::rtl::OUString sExcludeDir2 = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/user/registry/data/org/openoffice" ) );
85 static ::rtl::OUString sBasicType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("application/vnd.sun.star.basic-library"));
86 static ::rtl::OUString sDialogType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("application/vnd.sun.star.dialog-library"));
88 static ::rtl::OUString sConfigurationDataType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("application/vnd.sun.star.configuration-data"));
89 static ::rtl::OUString sConfigurationSchemaType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("application/vnd.sun.star.configuration-schema"));
91 // =============================================================================
92 // component operations
93 // =============================================================================
95 ::rtl::OUString ExtensionMigration_getImplementationName()
97 static ::rtl::OUString* pImplName = 0;
98 if ( !pImplName )
100 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
101 if ( !pImplName )
103 static ::rtl::OUString aImplName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.desktop.migration.Extensions" ) );
104 pImplName = &aImplName;
107 return *pImplName;
110 // -----------------------------------------------------------------------------
112 Sequence< ::rtl::OUString > ExtensionMigration_getSupportedServiceNames()
114 static Sequence< ::rtl::OUString >* pNames = 0;
115 if ( !pNames )
117 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
118 if ( !pNames )
120 static Sequence< ::rtl::OUString > aNames(1);
121 aNames.getArray()[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.migration.Extensions" ) );
122 pNames = &aNames;
125 return *pNames;
128 // =============================================================================
129 // ExtensionMigration
130 // =============================================================================
132 ExtensionMigration::ExtensionMigration(Reference< XComponentContext > const & ctx) :
133 m_ctx(ctx)
137 // -----------------------------------------------------------------------------
139 ExtensionMigration::~ExtensionMigration()
143 ::osl::FileBase::RC ExtensionMigration::checkAndCreateDirectory( INetURLObject& rDirURL )
145 ::osl::FileBase::RC aResult = ::osl::Directory::create( rDirURL.GetMainURL( INetURLObject::DECODE_TO_IURI ) );
146 if ( aResult == ::osl::FileBase::E_NOENT )
148 INetURLObject aBaseURL( rDirURL );
149 aBaseURL.removeSegment();
150 checkAndCreateDirectory( aBaseURL );
151 return ::osl::Directory::create( rDirURL.GetMainURL( INetURLObject::DECODE_TO_IURI ) );
153 else
155 return aResult;
159 void ExtensionMigration::prepareBasicLibs()
161 prepareBasicLibs(m_sSourceDir + ::rtl::OUString(
162 RTL_CONSTASCII_USTRINGPARAM("/user/basic/script.xlc")), m_scriptElements);
163 prepareBasicLibs(m_sSourceDir + ::rtl::OUString(
164 RTL_CONSTASCII_USTRINGPARAM("/user/basic/dialog.xlc")), m_dialogElements);
167 void ExtensionMigration::prepareBasicLibs(const ::rtl::OUString & sURL,
168 ::xmlscript::LibDescriptorArray & out_elements)
171 ::ucbhelper::Content ucb_content;
172 if (dp_misc::create_ucb_content( &ucb_content, sURL,
173 uno::Reference< ucb::XCommandEnvironment>(), false /* no throw */ ))
175 uno::Reference<xml::sax::XParser> xParser(
176 m_ctx->getServiceManager()->createInstanceWithContext(
177 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.sax.Parser")),
178 m_ctx ), UNO_QUERY_THROW );
180 xParser->setDocumentHandler( ::xmlscript::importLibraryContainer( &out_elements ) );
181 xml::sax::InputSource source;
182 source.aInputStream = ucb_content.openStream();
183 source.sSystemId = ucb_content.getURL();
184 xParser->parseStream( source );
186 //else
187 //The file need not exists
189 /* Checks if basic package is enabled in StarOffice 8. This is the case when the dialog.xlc or
190 the script.xlc in the user installation contains an entry for this package.
191 The passed package MUST be a basic package.
193 bool ExtensionMigration::isBasicPackageEnabled( const uno::Reference< deployment::XPackage > & xPkg)
195 ::rtl::OUString sScriptURL = xPkg->getURL();
196 if ( sScriptURL[ sScriptURL.getLength()-1 ] != '/' )
197 sScriptURL += ::rtl::OUString::createFromAscii("/");
198 sScriptURL += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("script.xlb") );
200 bool bEntryFound = false;
201 for ( sal_Int32 nPos = m_scriptElements.mnLibCount; nPos--; )
203 ::xmlscript::LibDescriptor const & descr =
204 m_scriptElements.mpLibs[ nPos ];
206 if (descr.aStorageURL.equals(sScriptURL))
208 bEntryFound = true;
209 break;
213 ::rtl::OUString sDialogURL = xPkg->getURL();
214 if ( sDialogURL[ sDialogURL.getLength()-1 ] != '/' )
215 sDialogURL += ::rtl::OUString::createFromAscii("/");
216 sScriptURL += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("dialog.xlb") );
218 if (!bEntryFound)
220 for ( sal_Int32 nPos = m_dialogElements.mnLibCount; nPos--; )
222 ::xmlscript::LibDescriptor const & descr =
223 m_dialogElements.mpLibs[ nPos ];
225 if (descr.aStorageURL.equals(sDialogURL))
227 bEntryFound = true;
228 break;
232 return bEntryFound;
234 /* This function only registers basic and dialog packages.
236 void ExtensionMigration::registerBasicPackage( const uno::Reference< deployment::XPackage > & xPkg)
238 const ::rtl::OUString sMediaType = xPkg->getPackageType()->getMediaType();
239 if ( (sMediaType.equals(sBasicType) || sMediaType.equals(sDialogType))
240 && isBasicPackageEnabled(xPkg))
242 xPkg->registerPackage(uno::Reference< task::XAbortChannel >(),
243 uno::Reference< ucb::XCommandEnvironment> ());
247 void ExtensionMigration::registerConfigurationPackage( const uno::Reference< deployment::XPackage > & xPkg)
249 const ::rtl::OUString sMediaType = xPkg->getPackageType()->getMediaType();
250 if ( (sMediaType.equals(sConfigurationDataType) || sMediaType.equals(sConfigurationSchemaType) ) )
252 xPkg->revokePackage(uno::Reference< task::XAbortChannel >(), uno::Reference< ucb::XCommandEnvironment> ());
253 xPkg->registerPackage(uno::Reference< task::XAbortChannel >(), uno::Reference< ucb::XCommandEnvironment> ());
257 bool ExtensionMigration::processExtensions( const ::rtl::OUString& sSourceDir, const ::rtl::OUString& sTargetDir )
259 if (!copy(sSourceDir, sTargetDir))
260 return false;
262 // Find all basic and script packages and reregister them
263 uno::Reference< deployment::XPackageManagerFactory > xPMF;
264 if (! ( m_ctx->getValueByName( ::rtl::OUString(
265 RTL_CONSTASCII_USTRINGPARAM("/singletons/com.sun.star.deployment.thePackageManagerFactory")))
266 >>= xPMF))
267 throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
268 "ExtensionsMigration: could not get thePackageManagerFactory")), 0);
270 const uno::Reference< deployment::XPackageManager > xPackageMgr =
271 xPMF->getPackageManager(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("user")));
273 if (!xPackageMgr.is())
274 throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
275 "ExtensionsMigration: could not get XPackageManager")), 0);
277 const uno::Sequence< uno::Reference< deployment::XPackage > > allPackages =
278 xPackageMgr->getDeployedPackages(
279 uno::Reference< task::XAbortChannel >(), uno::Reference< ucb::XCommandEnvironment> ());
281 for (int i = 0; i < allPackages.getLength(); i ++)
283 const uno::Reference< deployment::XPackage > aPackage = allPackages[i];
284 if ( aPackage->isBundle() )
286 const uno::Sequence< uno::Reference < deployment::XPackage > > seqPkg =
287 aPackage->getBundle(
288 uno::Reference< task::XAbortChannel >(),
289 uno::Reference< ucb::XCommandEnvironment> ());
291 for ( int k = 0; k < seqPkg.getLength(); k++ )
292 registerBasicPackage(seqPkg[k]);
294 for (int l = 0; l < seqPkg.getLength(); l++)
296 const ::rtl::OUString sMediaType = seqPkg[l]->getPackageType()->getMediaType();
297 beans::Optional<beans::Ambiguous<sal_Bool> > opt =
298 seqPkg[l]->isRegistered(uno::Reference< task::XAbortChannel >(), uno::Reference< ucb::XCommandEnvironment> ());
299 bool bRegistered = opt.IsPresent && opt.Value.IsAmbiguous == sal_False && opt.Value.Value == sal_True ? true : false;
301 if ( bRegistered && !sMediaType.equals(sBasicType) && !sMediaType.equals(sDialogType) )
303 seqPkg[l]->revokePackage(uno::Reference< task::XAbortChannel >(), uno::Reference< ucb::XCommandEnvironment> ());
304 seqPkg[l]->registerPackage(uno::Reference< task::XAbortChannel >(), uno::Reference< ucb::XCommandEnvironment> ());
308 else
310 registerBasicPackage(aPackage);
312 aPackage->revokePackage(uno::Reference< task::XAbortChannel >(), uno::Reference< ucb::XCommandEnvironment> ());
313 aPackage->registerPackage(uno::Reference< task::XAbortChannel >(), uno::Reference< ucb::XCommandEnvironment> ());
319 return true;
323 bool ExtensionMigration::isCompatibleBerkleyDb(const ::rtl::OUString& sSourceDir)
325 try
327 ::rtl::OUString sDb(sSourceDir + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
328 "/uno_packages.db")));
329 //check if the db exist at all. If not then the call to db_create would create
330 //the file.
331 ::osl::File f(sDb);
332 if (::osl::File::E_None != f.open(OpenFlag_Read))
334 f.close();
335 return false;
337 f.close();
339 //create a system path
340 ::rtl::OUString sSysPath;
341 if (::osl::File::getSystemPathFromFileURL(sDb, sSysPath ) != ::osl::File::E_None)
342 return false;
344 ::rtl::OString cstr_sysPath(
345 ::rtl::OUStringToOString( sSysPath, osl_getThreadTextEncoding() ) );
346 char const * pcstr_sysPath = cstr_sysPath.getStr();
348 //Open the db. If it works then we assume that the file was written with a
349 //compatible version of Berkeley Db
350 DB* pDB = NULL;
351 //using DB_RDONLY will return an "Invalid argument" error.
352 //DB_CREATE: only creates the file if it does not exist.
353 //An existing db is not modified.
354 if (0 != db_create(& pDB, 0, DB_CREATE))
355 return false;
357 if (0 != pDB->open(pDB, 0, pcstr_sysPath , 0, DB_HASH, DB_RDONLY, 0664 /* fs mode */))
358 return false;
360 pDB->close(pDB, 0);
362 catch (uno::Exception& )
364 return false;
367 return true;
370 bool ExtensionMigration::copy( const ::rtl::OUString& sSourceDir, const ::rtl::OUString& sTargetDir )
372 bool bRet = false;
373 if (! isCompatibleBerkleyDb(sSourceDir))
374 return false;
376 INetURLObject aSourceObj( sSourceDir );
377 INetURLObject aDestObj( sTargetDir );
378 String aName = aDestObj.getName();
379 aDestObj.removeSegment();
380 aDestObj.setFinalSlash();
384 ::ucbhelper::Content aDestPath( aDestObj.GetMainURL( INetURLObject::NO_DECODE ), uno::Reference< ucb::XCommandEnvironment > () );
385 uno::Reference< ucb::XCommandInfo > xInfo = aDestPath.getCommands();
386 ::rtl::OUString aTransferName = ::rtl::OUString::createFromAscii( "transfer" );
387 if ( xInfo->hasCommandByName( aTransferName ) )
389 aDestPath.executeCommand( aTransferName, uno::makeAny(
390 ucb::TransferInfo( sal_False, aSourceObj.GetMainURL( INetURLObject::NO_DECODE ), aName, ucb::NameClash::OVERWRITE ) ) );
391 bRet = true;
394 catch( uno::Exception& )
398 return bRet;
402 // -----------------------------------------------------------------------------
403 // XServiceInfo
404 // -----------------------------------------------------------------------------
406 ::rtl::OUString ExtensionMigration::getImplementationName() throw (RuntimeException)
408 return ExtensionMigration_getImplementationName();
411 // -----------------------------------------------------------------------------
413 sal_Bool ExtensionMigration::supportsService( const ::rtl::OUString& rServiceName ) throw (RuntimeException)
415 Sequence< ::rtl::OUString > aNames( getSupportedServiceNames() );
416 const ::rtl::OUString* pNames = aNames.getConstArray();
417 const ::rtl::OUString* pEnd = pNames + aNames.getLength();
418 for ( ; pNames != pEnd && !pNames->equals( rServiceName ); ++pNames )
421 return pNames != pEnd;
424 // -----------------------------------------------------------------------------
426 Sequence< ::rtl::OUString > ExtensionMigration::getSupportedServiceNames() throw (RuntimeException)
428 return ExtensionMigration_getSupportedServiceNames();
431 // -----------------------------------------------------------------------------
432 // XInitialization
433 // -----------------------------------------------------------------------------
435 void ExtensionMigration::initialize( const Sequence< Any >& aArguments ) throw (Exception, RuntimeException)
437 ::osl::MutexGuard aGuard( m_aMutex );
439 const Any* pIter = aArguments.getConstArray();
440 const Any* pEnd = pIter + aArguments.getLength();
441 for ( ; pIter != pEnd ; ++pIter )
443 beans::NamedValue aValue;
444 *pIter >>= aValue;
445 if ( aValue.Name.equalsAscii( "UserData" ) )
447 if ( !(aValue.Value >>= m_sSourceDir) )
449 OSL_ENSURE( false, "ExtensionMigration::initialize: argument UserData has wrong type!" );
451 break;
454 prepareBasicLibs();
457 TStringVectorPtr getContent( const ::rtl::OUString& rBaseURL )
459 TStringVectorPtr aResult( new TStringVector );
460 ::osl::Directory aDir( rBaseURL);
461 if ( aDir.open() == ::osl::FileBase::E_None )
463 // iterate over directory content
464 TStringVector aSubDirs;
465 ::osl::DirectoryItem aItem;
466 while ( aDir.getNextItem( aItem ) == ::osl::FileBase::E_None )
468 ::osl::FileStatus aFileStatus( FileStatusMask_Type | FileStatusMask_FileURL );
469 if ( aItem.getFileStatus( aFileStatus ) == ::osl::FileBase::E_None )
470 aResult->push_back( aFileStatus.getFileURL() );
474 return aResult;
477 // -----------------------------------------------------------------------------
478 // XJob
479 // -----------------------------------------------------------------------------
481 void ExtensionMigration::copyConfig( const ::rtl::OUString& sSourceDir, const ::rtl::OUString& sTargetDir )
483 ::rtl::OUString sEx1( m_sSourceDir );
484 sEx1 += sExcludeDir1;
485 ::rtl::OUString sEx2( m_sSourceDir );
486 sEx2 += sExcludeDir2;
488 TStringVectorPtr aList = getContent( sSourceDir );
489 TStringVector::const_iterator aI = aList->begin();
490 while ( aI != aList->end() )
492 ::rtl::OUString sSourceLocalName = aI->copy( sSourceDir.getLength() );
493 ::rtl::OUString aTemp = aI->copy( m_sSourceDir.getLength() );
494 if ( aTemp != sExcludeDir1 && aTemp != sExcludeDir2 )
496 ::rtl::OUString sTargetName = sTargetDir + sSourceLocalName;
497 copy( (*aI), sTargetName );
499 ++aI;
503 Any ExtensionMigration::execute( const Sequence< beans::NamedValue >& )
504 throw (lang::IllegalArgumentException, Exception, RuntimeException)
506 ::osl::MutexGuard aGuard( m_aMutex );
508 ::utl::Bootstrap::PathStatus aStatus = ::utl::Bootstrap::locateUserInstallation( m_sTargetDir );
509 if ( aStatus == ::utl::Bootstrap::PATH_EXISTS )
511 // copy all extensions
512 ::rtl::OUString sTargetDir(m_sTargetDir), sSourceDir( m_sSourceDir );
513 sTargetDir += sExtensionSubDir;
514 sSourceDir += sExtensionSubDir;
515 sSourceDir += sSubDirName;
516 sTargetDir += sSubDirName;
517 processExtensions( sSourceDir, sTargetDir );
519 // copy all user config settings in user/registry/data (except user/registry/data/org)
520 sSourceDir = m_sSourceDir;
521 sSourceDir += sConfigDir;
522 sTargetDir = m_sTargetDir;
523 sTargetDir += sConfigDir;
524 copyConfig( sSourceDir, sTargetDir );
526 // copy all user config settings in user/registry/data/org (except user/registry/data/org/openoffice)
527 sSourceDir = m_sSourceDir;
528 sSourceDir += sOrgDir;
529 sTargetDir = m_sTargetDir;
530 sTargetDir += sOrgDir;
531 copyConfig( sSourceDir, sTargetDir );
534 return Any();
537 // =============================================================================
538 // component operations
539 // =============================================================================
541 Reference< XInterface > SAL_CALL ExtensionMigration_create(
542 Reference< XComponentContext > const & ctx )
543 SAL_THROW( () )
545 return static_cast< lang::XTypeProvider * >( new ExtensionMigration(
546 ctx) );
549 // -----------------------------------------------------------------------------
551 //.........................................................................
552 } // namespace migration
553 //.........................................................................