From d7cc1b57990e1ebc2e1f2a4380dd8e66b0eff158 Mon Sep 17 00:00:00 2001 From: David Tardon Date: Thu, 10 Feb 2011 13:54:19 +0100 Subject: [PATCH] rhbz#649310 don't crash deregistering diff. platform ext. This happens, for example, if one switches between, lets say, x86 and x86_64 systems and has the same /home mounted from both. Then platform-dependent extensions from one system does not exist on the other one, but must still be deregistered correctly. --- .../deployment/registry/component/dp_component.cxx | 164 +++++++++++++++++++- 1 files changed, 159 insertions(+), 5 deletions(-) diff --git a/desktop/source/deployment/registry/component/dp_component.cxx b/desktop/source/deployment/registry/component/dp_component.cxx index b7fe0b1..d4cb5dd 100644 --- a/desktop/source/deployment/registry/component/dp_component.cxx +++ b/desktop/source/deployment/registry/component/dp_component.cxx @@ -192,6 +192,42 @@ class BackendImpl : public ::dp_registry::backend::PackageRegistryBackend OUString const & identifier); }; friend class TypelibraryPackageImpl; + + /** Serves for unregistering packages that were registered on a + different platform. This can happen if one has remotely mounted + /home, for example. + */ + class OtherPlatformPackageImpl : public ::dp_registry::backend::Package + { + public: + OtherPlatformPackageImpl( + ::rtl::Reference const & myBackend, + OUString const & url, OUString const & name, + Reference const & xPackageType, + bool bRemoved, OUString const & identifier, OUString const& rPlatform); + + private: + BackendImpl * getMyBackend() const; + + const Reference impl_openRDB() const; + const Reference impl_createInstance(OUString const& rService) const; + + // Package + virtual beans::Optional< beans::Ambiguous > isRegistered_( + ::osl::ResettableMutexGuard & guard, + ::rtl::Reference const & abortChannel, + Reference const & xCmdEnv ); + virtual void processPackage_( + ::osl::ResettableMutexGuard & guard, + bool registerPackage, + bool startup, + ::rtl::Reference const & abortChannel, + Reference const & xCmdEnv ); + + private: + OUString const m_aPlatform; + }; + friend class OtherPlatformPackageImpl; t_stringlist m_jar_typelibs; t_stringlist m_rdb_typelibs; @@ -694,16 +730,30 @@ Reference BackendImpl::bindPackage_( INetContentTypeParameter const * param = params.find( ByteString("platform") ); - if (param == 0 || platform_fits( param->m_sValue )) { + bool bPlatformFits(param == 0); + String aPlatform; + if (!bPlatformFits) // platform is specified, we have to check + { + aPlatform = param->m_sValue; + bPlatformFits = platform_fits(aPlatform); + } + // If the package is being removed, do not care whether + // platform fits. We won't be using it anyway. + if (bPlatformFits || bRemoved) { param = params.find( ByteString("type") ); if (param != 0) { String const & value = param->m_sValue; if (value.EqualsIgnoreCaseAscii("native")) { - return new BackendImpl::ComponentPackageImpl( - this, url, name, m_xDynComponentTypeInfo, - OUSTR("com.sun.star.loader.SharedLibrary"), - bRemoved, identifier); + if (bPlatformFits) + return new BackendImpl::ComponentPackageImpl( + this, url, name, m_xDynComponentTypeInfo, + OUSTR("com.sun.star.loader.SharedLibrary"), + bRemoved, identifier); + else + return new BackendImpl::OtherPlatformPackageImpl( + this, url, name, m_xDynComponentTypeInfo, + bRemoved, identifier, aPlatform); } if (value.EqualsIgnoreCaseAscii("Java")) { return new BackendImpl::ComponentPackageImpl( @@ -1567,6 +1617,110 @@ void BackendImpl::TypelibraryPackageImpl::processPackage_( } } +BackendImpl::OtherPlatformPackageImpl::OtherPlatformPackageImpl( + ::rtl::Reference const & myBackend, + OUString const & url, OUString const & name, + Reference const & xPackageType, + bool bRemoved, OUString const & identifier, OUString const& rPlatform) + : Package(myBackend, url, name, name, xPackageType, bRemoved, identifier) + , m_aPlatform(rPlatform) +{ + OSL_PRECOND(bRemoved, "this class can only be used for removing packages!"); +} + +BackendImpl * +BackendImpl::OtherPlatformPackageImpl::getMyBackend() const +{ + BackendImpl * pBackend = static_cast(m_myBackend.get()); + if (NULL == pBackend) + { + //Throws a DisposedException + check(); + //We should never get here... + throw RuntimeException( + OUSTR("Failed to get the BackendImpl"), + static_cast(const_cast(this))); + } + return pBackend; +} + +Reference const +BackendImpl::OtherPlatformPackageImpl::impl_openRDB() const +{ + OUString const aRDB(m_aPlatform + OUString(RTL_CONSTASCII_USTRINGPARAM(".rdb"))); + OUString const aRDBPath(makeURL(getMyBackend()->getCachePath(), aRDB)); + + Reference xRegistry; + + try + { + xRegistry.set( + impl_createInstance( + OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.registry.SimpleRegistry"))), + UNO_QUERY) + ; + if (xRegistry.is()) + xRegistry->open(expandUnoRcUrl(aRDBPath), false, false); + } + catch (registry::InvalidRegistryException const&) + { + // If the registry does not exist, we do not need to bother at all + xRegistry.set(0); + } + + OSL_POSTCOND(xRegistry.is(), "could not create registry for the package's platform"); + return xRegistry; +} + +Reference const +BackendImpl::OtherPlatformPackageImpl::impl_createInstance(OUString const& rService) +const +{ + Reference const xContext(getMyBackend()->getComponentContext()); + OSL_ASSERT(xContext.is()); + Reference xService; + if (xContext.is()) + xService.set(xContext->getServiceManager()->createInstanceWithContext(rService, xContext)); + return xService; +} + +beans::Optional > +BackendImpl::OtherPlatformPackageImpl::isRegistered_( + ::osl::ResettableMutexGuard& /* guard */, + ::rtl::Reference const& /* abortChannel */, + Reference const& /* xCmdEnv */ ) +{ + return beans::Optional >(sal_True, + beans::Ambiguous(sal_True, sal_False)); +} + +void +BackendImpl::OtherPlatformPackageImpl::processPackage_( + ::osl::ResettableMutexGuard& /* guard */, + bool bRegisterPackage, + bool /* bStartup */, + ::rtl::Reference const& /* abortChannel */, + Reference const& /* xCmdEnv */) +{ + OSL_PRECOND(!bRegisterPackage, "this class can only be used for removing packages!"); + (void) bRegisterPackage; + + OUString const aURL(getURL()); + + Reference const xServicesRDB(impl_openRDB()); + Reference const xImplReg( + impl_createInstance( + OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.registry.ImplementationRegistration"))), + UNO_QUERY) + ; + if (xImplReg.is() && xServicesRDB.is()) + xImplReg->revokeImplementation(aURL, xServicesRDB); + if (xServicesRDB.is()) + xServicesRDB->close(); + + getMyBackend()->deleteDataFromDb(aURL); +} + } // anon namespace namespace sdecl = comphelper::service_decl; -- 1.7.4