summaryrefslogtreecommitdiff
path: root/desktop/source/migration/services/extensionmigration.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'desktop/source/migration/services/extensionmigration.cxx')
-rwxr-xr-xdesktop/source/migration/services/extensionmigration.cxx540
1 files changed, 540 insertions, 0 deletions
diff --git a/desktop/source/migration/services/extensionmigration.cxx b/desktop/source/migration/services/extensionmigration.cxx
new file mode 100755
index 000000000000..a926f17c0c19
--- /dev/null
+++ b/desktop/source/migration/services/extensionmigration.cxx
@@ -0,0 +1,540 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_desktop.hxx"
+#include "extensionmigration.hxx"
+#include <tools/urlobj.hxx>
+#include <unotools/bootstrap.hxx>
+#include <unotools/ucbstreamhelper.hxx>
+#include <ucbhelper/content.hxx>
+#include <com/sun/star/ucb/XCommandInfo.hpp>
+#include <com/sun/star/ucb/TransferInfo.hpp>
+#include <com/sun/star/ucb/NameClash.hpp>
+#include "comphelper/processfactory.hxx"
+#include "com/sun/star/deployment/XPackageManagerFactory.hpp"
+#include "com/sun/star/ucb/XCommandEnvironment.hpp"
+#include "com/sun/star/xml/sax/XParser.hpp"
+#include "rtl/instance.hxx"
+#include "osl/file.hxx"
+#include "osl/thread.h"
+
+#include "xmlscript/xmllib_imexp.hxx"
+#include "../../deployment/inc/dp_ucb.h"
+
+#ifdef SYSTEM_DB
+#include <db.h>
+#else
+#include <berkeleydb/db.h>
+#endif
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+namespace {
+
+ struct LibDescriptor :
+ public rtl::StaticWithInit<const ::xmlscript::LibDescriptorArray, LibDescriptor> {
+ const ::xmlscript::LibDescriptorArray operator () () {
+
+
+ return ::xmlscript::LibDescriptorArray();
+ }
+};
+}
+//.........................................................................
+namespace migration
+{
+//.........................................................................
+
+
+ static ::rtl::OUString sExtensionSubDir = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/user/uno_packages/" ) );
+ static ::rtl::OUString sSubDirName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cache" ) );
+ static ::rtl::OUString sConfigDir = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/user/registry/data" ) );
+ static ::rtl::OUString sOrgDir = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/user/registry/data/org" ) );
+ static ::rtl::OUString sExcludeDir1 = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/user/registry/data/org" ) );
+ static ::rtl::OUString sExcludeDir2 = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/user/registry/data/org/openoffice" ) );
+
+ static ::rtl::OUString sBasicType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("application/vnd.sun.star.basic-library"));
+ static ::rtl::OUString sDialogType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("application/vnd.sun.star.dialog-library"));
+
+ static ::rtl::OUString sConfigurationDataType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("application/vnd.sun.star.configuration-data"));
+ static ::rtl::OUString sConfigurationSchemaType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("application/vnd.sun.star.configuration-schema"));
+
+ // =============================================================================
+ // component operations
+ // =============================================================================
+
+ ::rtl::OUString ExtensionMigration_getImplementationName()
+ {
+ static ::rtl::OUString* pImplName = 0;
+ if ( !pImplName )
+ {
+ ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
+ if ( !pImplName )
+ {
+ static ::rtl::OUString aImplName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.desktop.migration.Extensions" ) );
+ pImplName = &aImplName;
+ }
+ }
+ return *pImplName;
+ }
+
+ // -----------------------------------------------------------------------------
+
+ Sequence< ::rtl::OUString > ExtensionMigration_getSupportedServiceNames()
+ {
+ static Sequence< ::rtl::OUString >* pNames = 0;
+ if ( !pNames )
+ {
+ ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
+ if ( !pNames )
+ {
+ static Sequence< ::rtl::OUString > aNames(1);
+ aNames.getArray()[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.migration.Extensions" ) );
+ pNames = &aNames;
+ }
+ }
+ return *pNames;
+ }
+
+ // =============================================================================
+ // ExtensionMigration
+ // =============================================================================
+
+ ExtensionMigration::ExtensionMigration(Reference< XComponentContext > const & ctx) :
+ m_ctx(ctx)
+ {
+ }
+
+ // -----------------------------------------------------------------------------
+
+ ExtensionMigration::~ExtensionMigration()
+ {
+ }
+
+ ::osl::FileBase::RC ExtensionMigration::checkAndCreateDirectory( INetURLObject& rDirURL )
+ {
+ ::osl::FileBase::RC aResult = ::osl::Directory::create( rDirURL.GetMainURL( INetURLObject::DECODE_TO_IURI ) );
+ if ( aResult == ::osl::FileBase::E_NOENT )
+ {
+ INetURLObject aBaseURL( rDirURL );
+ aBaseURL.removeSegment();
+ checkAndCreateDirectory( aBaseURL );
+ return ::osl::Directory::create( rDirURL.GetMainURL( INetURLObject::DECODE_TO_IURI ) );
+ }
+ else
+ {
+ return aResult;
+ }
+ }
+
+ void ExtensionMigration::prepareBasicLibs()
+ {
+ prepareBasicLibs(m_sSourceDir + ::rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("/user/basic/script.xlc")), m_scriptElements);
+ prepareBasicLibs(m_sSourceDir + ::rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("/user/basic/dialog.xlc")), m_dialogElements);
+ }
+
+ void ExtensionMigration::prepareBasicLibs(const ::rtl::OUString & sURL,
+ ::xmlscript::LibDescriptorArray & out_elements)
+ {
+
+ ::ucbhelper::Content ucb_content;
+ if (dp_misc::create_ucb_content( &ucb_content, sURL,
+ uno::Reference< ucb::XCommandEnvironment>(), false /* no throw */ ))
+ {
+ uno::Reference<xml::sax::XParser> xParser(
+ m_ctx->getServiceManager()->createInstanceWithContext(
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.sax.Parser")),
+ m_ctx ), UNO_QUERY_THROW );
+
+ xParser->setDocumentHandler( ::xmlscript::importLibraryContainer( &out_elements ) );
+ xml::sax::InputSource source;
+ source.aInputStream = ucb_content.openStream();
+ source.sSystemId = ucb_content.getURL();
+ xParser->parseStream( source );
+ }
+ //else
+ //The file need not exists
+ }
+ /* Checks if basic package is enabled in StarOffice 8. This is the case when the dialog.xlc or
+ the script.xlc in the user installation contains an entry for this package.
+ The passed package MUST be a basic package.
+ */
+ bool ExtensionMigration::isBasicPackageEnabled( const uno::Reference< deployment::XPackage > & xPkg)
+ {
+ ::rtl::OUString sScriptURL = xPkg->getURL();
+ if ( sScriptURL[ sScriptURL.getLength()-1 ] != '/' )
+ sScriptURL += ::rtl::OUString::createFromAscii("/");
+ sScriptURL += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("script.xlb") );
+
+ bool bEntryFound = false;
+ for ( sal_Int32 nPos = m_scriptElements.mnLibCount; nPos--; )
+ {
+ ::xmlscript::LibDescriptor const & descr =
+ m_scriptElements.mpLibs[ nPos ];
+
+ if (descr.aStorageURL.equals(sScriptURL))
+ {
+ bEntryFound = true;
+ break;
+ }
+ }
+
+ ::rtl::OUString sDialogURL = xPkg->getURL();
+ if ( sDialogURL[ sDialogURL.getLength()-1 ] != '/' )
+ sDialogURL += ::rtl::OUString::createFromAscii("/");
+ sScriptURL += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("dialog.xlb") );
+
+ if (!bEntryFound)
+ {
+ for ( sal_Int32 nPos = m_dialogElements.mnLibCount; nPos--; )
+ {
+ ::xmlscript::LibDescriptor const & descr =
+ m_dialogElements.mpLibs[ nPos ];
+
+ if (descr.aStorageURL.equals(sDialogURL))
+ {
+ bEntryFound = true;
+ break;
+ }
+ }
+ }
+ return bEntryFound;
+ }
+ /* This function only registers basic and dialog packages.
+ */
+ void ExtensionMigration::registerBasicPackage( const uno::Reference< deployment::XPackage > & xPkg)
+ {
+ const ::rtl::OUString sMediaType = xPkg->getPackageType()->getMediaType();
+ if ( (sMediaType.equals(sBasicType) || sMediaType.equals(sDialogType))
+ && isBasicPackageEnabled(xPkg))
+ {
+ xPkg->registerPackage(uno::Reference< task::XAbortChannel >(),
+ uno::Reference< ucb::XCommandEnvironment> ());
+ }
+ }
+
+ bool ExtensionMigration::processExtensions( const ::rtl::OUString& sSourceDir, const ::rtl::OUString& sTargetDir )
+ {
+ if (!copy(sSourceDir, sTargetDir))
+ return false;
+
+ // Find all basic and script packages and reregister them
+ uno::Reference< deployment::XPackageManagerFactory > xPMF;
+ if (! ( m_ctx->getValueByName( ::rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("/singletons/com.sun.star.deployment.thePackageManagerFactory")))
+ >>= xPMF))
+ throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
+ "ExtensionsMigration: could not get thePackageManagerFactory")), 0);
+
+ const uno::Reference< deployment::XPackageManager > xPackageMgr =
+ xPMF->getPackageManager(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("user")));
+
+ if (!xPackageMgr.is())
+ throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
+ "ExtensionsMigration: could not get XPackageManager")), 0);
+
+ const uno::Sequence< uno::Reference< deployment::XPackage > > allPackages =
+ xPackageMgr->getDeployedPackages(
+ uno::Reference< task::XAbortChannel >(), uno::Reference< ucb::XCommandEnvironment> ());
+
+ for (int i = 0; i < allPackages.getLength(); i ++)
+ {
+ const uno::Reference< deployment::XPackage > aPackage = allPackages[i];
+ if ( aPackage->isBundle() )
+ {
+ const uno::Sequence< uno::Reference < deployment::XPackage > > seqPkg =
+ aPackage->getBundle(
+ uno::Reference< task::XAbortChannel >(),
+ uno::Reference< ucb::XCommandEnvironment> ());
+
+ for ( int k = 0; k < seqPkg.getLength(); k++ )
+ registerBasicPackage(seqPkg[k]);
+
+ for (int l = 0; l < seqPkg.getLength(); l++)
+ {
+ const ::rtl::OUString sMediaType = seqPkg[l]->getPackageType()->getMediaType();
+ beans::Optional<beans::Ambiguous<sal_Bool> > opt =
+ seqPkg[l]->isRegistered(uno::Reference< task::XAbortChannel >(), uno::Reference< ucb::XCommandEnvironment> ());
+ bool bRegistered = opt.IsPresent && opt.Value.IsAmbiguous == sal_False && opt.Value.Value == sal_True ? true : false;
+
+ if ( bRegistered && !sMediaType.equals(sBasicType) && !sMediaType.equals(sDialogType) )
+ {
+ seqPkg[l]->revokePackage(uno::Reference< task::XAbortChannel >(), uno::Reference< ucb::XCommandEnvironment> ());
+ seqPkg[l]->registerPackage(uno::Reference< task::XAbortChannel >(), uno::Reference< ucb::XCommandEnvironment> ());
+ }
+ }
+ }
+ else
+ {
+ registerBasicPackage(aPackage);
+ {
+ aPackage->revokePackage(uno::Reference< task::XAbortChannel >(), uno::Reference< ucb::XCommandEnvironment> ());
+ aPackage->registerPackage(uno::Reference< task::XAbortChannel >(), uno::Reference< ucb::XCommandEnvironment> ());
+ }
+ }
+ }
+
+
+ return true;
+
+ }
+
+bool ExtensionMigration::isCompatibleBerkleyDb(const ::rtl::OUString& sSourceDir)
+{
+ try
+ {
+ ::rtl::OUString sDb(sSourceDir + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
+ "/uno_packages.db")));
+ //check if the db exist at all. If not then the call to db_create would create
+ //the file.
+ ::osl::File f(sDb);
+ if (::osl::File::E_None != f.open(OpenFlag_Read))
+ {
+ f.close();
+ return false;
+ }
+ f.close();
+
+ //create a system path
+ ::rtl::OUString sSysPath;
+ if (::osl::File::getSystemPathFromFileURL(sDb, sSysPath ) != ::osl::File::E_None)
+ return false;
+
+ ::rtl::OString cstr_sysPath(
+ ::rtl::OUStringToOString( sSysPath, osl_getThreadTextEncoding() ) );
+ char const * pcstr_sysPath = cstr_sysPath.getStr();
+
+ //Open the db. If it works then we assume that the file was written with a
+ //compatible version of Berkeley Db
+ DB* pDB = NULL;
+ //using DB_RDONLY will return an "Invalid argument" error.
+ //DB_CREATE: only creates the file if it does not exist.
+ //An existing db is not modified.
+ if (0 != db_create(& pDB, 0, DB_CREATE))
+ return false;
+
+ if (0 != pDB->open(pDB, 0, pcstr_sysPath , 0, DB_HASH, DB_RDONLY, 0664 /* fs mode */))
+ return false;
+
+ pDB->close(pDB, 0);
+ }
+ catch (uno::Exception& )
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ExtensionMigration::copy( const ::rtl::OUString& sSourceDir, const ::rtl::OUString& sTargetDir )
+{
+ bool bRet = false;
+ if (! isCompatibleBerkleyDb(sSourceDir))
+ return false;
+
+ INetURLObject aSourceObj( sSourceDir );
+ INetURLObject aDestObj( sTargetDir );
+ String aName = aDestObj.getName();
+ aDestObj.removeSegment();
+ aDestObj.setFinalSlash();
+
+ try
+ {
+ ::ucbhelper::Content aDestPath( aDestObj.GetMainURL( INetURLObject::NO_DECODE ), uno::Reference< ucb::XCommandEnvironment > () );
+ uno::Reference< ucb::XCommandInfo > xInfo = aDestPath.getCommands();
+ ::rtl::OUString aTransferName = ::rtl::OUString::createFromAscii( "transfer" );
+ if ( xInfo->hasCommandByName( aTransferName ) )
+ {
+ aDestPath.executeCommand( aTransferName, uno::makeAny(
+ ucb::TransferInfo( sal_False, aSourceObj.GetMainURL( INetURLObject::NO_DECODE ), aName, ucb::NameClash::OVERWRITE ) ) );
+ bRet = true;
+ }
+ }
+ catch( uno::Exception& )
+ {
+ }
+
+ return bRet;
+}
+
+
+ // -----------------------------------------------------------------------------
+ // XServiceInfo
+ // -----------------------------------------------------------------------------
+
+ ::rtl::OUString ExtensionMigration::getImplementationName() throw (RuntimeException)
+ {
+ return ExtensionMigration_getImplementationName();
+ }
+
+ // -----------------------------------------------------------------------------
+
+ sal_Bool ExtensionMigration::supportsService( const ::rtl::OUString& rServiceName ) throw (RuntimeException)
+ {
+ Sequence< ::rtl::OUString > aNames( getSupportedServiceNames() );
+ const ::rtl::OUString* pNames = aNames.getConstArray();
+ const ::rtl::OUString* pEnd = pNames + aNames.getLength();
+ for ( ; pNames != pEnd && !pNames->equals( rServiceName ); ++pNames )
+ ;
+
+ return pNames != pEnd;
+ }
+
+ // -----------------------------------------------------------------------------
+
+ Sequence< ::rtl::OUString > ExtensionMigration::getSupportedServiceNames() throw (RuntimeException)
+ {
+ return ExtensionMigration_getSupportedServiceNames();
+ }
+
+ // -----------------------------------------------------------------------------
+ // XInitialization
+ // -----------------------------------------------------------------------------
+
+ void ExtensionMigration::initialize( const Sequence< Any >& aArguments ) throw (Exception, RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ const Any* pIter = aArguments.getConstArray();
+ const Any* pEnd = pIter + aArguments.getLength();
+ for ( ; pIter != pEnd ; ++pIter )
+ {
+ beans::NamedValue aValue;
+ *pIter >>= aValue;
+ if ( aValue.Name.equalsAscii( "UserData" ) )
+ {
+ if ( !(aValue.Value >>= m_sSourceDir) )
+ {
+ OSL_ENSURE( false, "ExtensionMigration::initialize: argument UserData has wrong type!" );
+ }
+ break;
+ }
+ }
+ prepareBasicLibs();
+ }
+
+ TStringVectorPtr getContent( const ::rtl::OUString& rBaseURL )
+ {
+ TStringVectorPtr aResult( new TStringVector );
+ ::osl::Directory aDir( rBaseURL);
+ if ( aDir.open() == ::osl::FileBase::E_None )
+ {
+ // iterate over directory content
+ TStringVector aSubDirs;
+ ::osl::DirectoryItem aItem;
+ while ( aDir.getNextItem( aItem ) == ::osl::FileBase::E_None )
+ {
+ ::osl::FileStatus aFileStatus( FileStatusMask_Type | FileStatusMask_FileURL );
+ if ( aItem.getFileStatus( aFileStatus ) == ::osl::FileBase::E_None )
+ aResult->push_back( aFileStatus.getFileURL() );
+ }
+ }
+
+ return aResult;
+ }
+
+ // -----------------------------------------------------------------------------
+ // XJob
+ // -----------------------------------------------------------------------------
+
+void ExtensionMigration::copyConfig( const ::rtl::OUString& sSourceDir, const ::rtl::OUString& sTargetDir )
+{
+ ::rtl::OUString sEx1( m_sSourceDir );
+ sEx1 += sExcludeDir1;
+ ::rtl::OUString sEx2( m_sSourceDir );
+ sEx2 += sExcludeDir2;
+
+ TStringVectorPtr aList = getContent( sSourceDir );
+ TStringVector::const_iterator aI = aList->begin();
+ while ( aI != aList->end() )
+ {
+ ::rtl::OUString sSourceLocalName = aI->copy( sSourceDir.getLength() );
+ ::rtl::OUString aTemp = aI->copy( m_sSourceDir.getLength() );
+ if ( aTemp != sExcludeDir1 && aTemp != sExcludeDir2 )
+ {
+ ::rtl::OUString sTargetName = sTargetDir + sSourceLocalName;
+ copy( (*aI), sTargetName );
+ }
+ ++aI;
+ }
+}
+
+ Any ExtensionMigration::execute( const Sequence< beans::NamedValue >& )
+ throw (lang::IllegalArgumentException, Exception, RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ ::utl::Bootstrap::PathStatus aStatus = ::utl::Bootstrap::locateUserInstallation( m_sTargetDir );
+ if ( aStatus == ::utl::Bootstrap::PATH_EXISTS )
+ {
+ // copy all extensions
+ ::rtl::OUString sTargetDir(m_sTargetDir), sSourceDir( m_sSourceDir );
+ sTargetDir += sExtensionSubDir;
+ sSourceDir += sExtensionSubDir;
+ sSourceDir += sSubDirName;
+ sTargetDir += sSubDirName;
+ processExtensions( sSourceDir, sTargetDir );
+
+ // copy all user config settings in user/registry/data (except user/registry/data/org)
+ sSourceDir = m_sSourceDir;
+ sSourceDir += sConfigDir;
+ sTargetDir = m_sTargetDir;
+ sTargetDir += sConfigDir;
+ copyConfig( sSourceDir, sTargetDir );
+
+ // copy all user config settings in user/registry/data/org (except user/registry/data/org/openoffice)
+ sSourceDir = m_sSourceDir;
+ sSourceDir += sOrgDir;
+ sTargetDir = m_sTargetDir;
+ sTargetDir += sOrgDir;
+ copyConfig( sSourceDir, sTargetDir );
+ }
+
+ return Any();
+ }
+
+ // =============================================================================
+ // component operations
+ // =============================================================================
+
+ Reference< XInterface > SAL_CALL ExtensionMigration_create(
+ Reference< XComponentContext > const & ctx )
+ SAL_THROW( () )
+ {
+ return static_cast< lang::XTypeProvider * >( new ExtensionMigration(
+ ctx) );
+ }
+
+ // -----------------------------------------------------------------------------
+
+//.........................................................................
+} // namespace migration
+//.........................................................................