1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 29*cdf0e10cSrcweir #include "precompiled_desktop.hxx" 30*cdf0e10cSrcweir 31*cdf0e10cSrcweir #include "dp_help.hrc" 32*cdf0e10cSrcweir #include "dp_backend.h" 33*cdf0e10cSrcweir #include "dp_helpbackenddb.hxx" 34*cdf0e10cSrcweir #include "dp_ucb.h" 35*cdf0e10cSrcweir #include "rtl/uri.hxx" 36*cdf0e10cSrcweir #include "osl/file.hxx" 37*cdf0e10cSrcweir #include "rtl/bootstrap.hxx" 38*cdf0e10cSrcweir #include "ucbhelper/content.hxx" 39*cdf0e10cSrcweir #include "comphelper/servicedecl.hxx" 40*cdf0e10cSrcweir #include "svl/inettype.hxx" 41*cdf0e10cSrcweir #include "unotools/pathoptions.hxx" 42*cdf0e10cSrcweir 43*cdf0e10cSrcweir #include <l10ntools/compilehelp.hxx> 44*cdf0e10cSrcweir #include <com/sun/star/ucb/XSimpleFileAccess.hpp> 45*cdf0e10cSrcweir #include <com/sun/star/util/XMacroExpander.hpp> 46*cdf0e10cSrcweir #include <com/sun/star/uri/XUriReferenceFactory.hpp> 47*cdf0e10cSrcweir #include <com/sun/star/uri/XVndSunStarExpandUrl.hpp> 48*cdf0e10cSrcweir #include <com/sun/star/script/XInvocation.hpp> 49*cdf0e10cSrcweir #include "boost/optional.hpp" 50*cdf0e10cSrcweir 51*cdf0e10cSrcweir using namespace ::dp_misc; 52*cdf0e10cSrcweir using namespace ::com::sun::star; 53*cdf0e10cSrcweir using namespace ::com::sun::star::uno; 54*cdf0e10cSrcweir using namespace ::com::sun::star::ucb; 55*cdf0e10cSrcweir using ::rtl::OUString; 56*cdf0e10cSrcweir 57*cdf0e10cSrcweir namespace dp_registry { 58*cdf0e10cSrcweir namespace backend { 59*cdf0e10cSrcweir namespace help { 60*cdf0e10cSrcweir namespace { 61*cdf0e10cSrcweir 62*cdf0e10cSrcweir //============================================================================== 63*cdf0e10cSrcweir class BackendImpl : public ::dp_registry::backend::PackageRegistryBackend 64*cdf0e10cSrcweir { 65*cdf0e10cSrcweir class PackageImpl : public ::dp_registry::backend::Package 66*cdf0e10cSrcweir { 67*cdf0e10cSrcweir BackendImpl * getMyBackend() const; 68*cdf0e10cSrcweir 69*cdf0e10cSrcweir // HelpBackendDb::Data m_dbData; 70*cdf0e10cSrcweir 71*cdf0e10cSrcweir // Package 72*cdf0e10cSrcweir virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_( 73*cdf0e10cSrcweir ::osl::ResettableMutexGuard & guard, 74*cdf0e10cSrcweir ::rtl::Reference<AbortChannel> const & abortChannel, 75*cdf0e10cSrcweir Reference<XCommandEnvironment> const & xCmdEnv ); 76*cdf0e10cSrcweir virtual void processPackage_( 77*cdf0e10cSrcweir ::osl::ResettableMutexGuard & guard, 78*cdf0e10cSrcweir bool registerPackage, 79*cdf0e10cSrcweir bool startup, 80*cdf0e10cSrcweir ::rtl::Reference<AbortChannel> const & abortChannel, 81*cdf0e10cSrcweir Reference<XCommandEnvironment> const & xCmdEnv ); 82*cdf0e10cSrcweir 83*cdf0e10cSrcweir 84*cdf0e10cSrcweir public: 85*cdf0e10cSrcweir PackageImpl( 86*cdf0e10cSrcweir ::rtl::Reference<PackageRegistryBackend> const & myBackend, 87*cdf0e10cSrcweir OUString const & url, OUString const & name, 88*cdf0e10cSrcweir Reference<deployment::XPackageTypeInfo> const & xPackageType, 89*cdf0e10cSrcweir bool bRemoved, OUString const & identifier); 90*cdf0e10cSrcweir 91*cdf0e10cSrcweir bool extensionContainsCompiledHelp(); 92*cdf0e10cSrcweir 93*cdf0e10cSrcweir //XPackage 94*cdf0e10cSrcweir virtual css::beans::Optional< ::rtl::OUString > SAL_CALL getRegistrationDataURL() 95*cdf0e10cSrcweir throw (deployment::ExtensionRemovedException, css::uno::RuntimeException); 96*cdf0e10cSrcweir }; 97*cdf0e10cSrcweir friend class PackageImpl; 98*cdf0e10cSrcweir 99*cdf0e10cSrcweir // PackageRegistryBackend 100*cdf0e10cSrcweir virtual Reference<deployment::XPackage> bindPackage_( 101*cdf0e10cSrcweir OUString const & url, OUString const & mediaType, 102*cdf0e10cSrcweir sal_Bool bRemoved, OUString const & identifier, 103*cdf0e10cSrcweir Reference<XCommandEnvironment> const & xCmdEnv ); 104*cdf0e10cSrcweir 105*cdf0e10cSrcweir void implProcessHelp( PackageImpl * package, bool doRegisterPackage, 106*cdf0e10cSrcweir Reference<ucb::XCommandEnvironment> const & xCmdEnv); 107*cdf0e10cSrcweir void implCollectXhpFiles( const rtl::OUString& aDir, 108*cdf0e10cSrcweir std::vector< rtl::OUString >& o_rXhpFileVector ); 109*cdf0e10cSrcweir 110*cdf0e10cSrcweir void addDataToDb(OUString const & url, HelpBackendDb::Data const & data); 111*cdf0e10cSrcweir ::boost::optional<HelpBackendDb::Data> readDataFromDb(OUString const & url); 112*cdf0e10cSrcweir bool hasActiveEntry(OUString const & url); 113*cdf0e10cSrcweir void revokeEntryFromDb(OUString const & url); 114*cdf0e10cSrcweir bool activateEntry(OUString const & url); 115*cdf0e10cSrcweir 116*cdf0e10cSrcweir Reference< ucb::XSimpleFileAccess > getFileAccess( void ); 117*cdf0e10cSrcweir Reference< ucb::XSimpleFileAccess > m_xSFA; 118*cdf0e10cSrcweir 119*cdf0e10cSrcweir const Reference<deployment::XPackageTypeInfo> m_xHelpTypeInfo; 120*cdf0e10cSrcweir Sequence< Reference<deployment::XPackageTypeInfo> > m_typeInfos; 121*cdf0e10cSrcweir std::auto_ptr<HelpBackendDb> m_backendDb; 122*cdf0e10cSrcweir 123*cdf0e10cSrcweir public: 124*cdf0e10cSrcweir BackendImpl( Sequence<Any> const & args, 125*cdf0e10cSrcweir Reference<XComponentContext> const & xComponentContext ); 126*cdf0e10cSrcweir 127*cdf0e10cSrcweir // XPackageRegistry 128*cdf0e10cSrcweir virtual Sequence< Reference<deployment::XPackageTypeInfo> > SAL_CALL 129*cdf0e10cSrcweir getSupportedPackageTypes() throw (RuntimeException); 130*cdf0e10cSrcweir virtual void SAL_CALL packageRemoved(OUString const & url, OUString const & mediaType) 131*cdf0e10cSrcweir throw (deployment::DeploymentException, 132*cdf0e10cSrcweir uno::RuntimeException); 133*cdf0e10cSrcweir 134*cdf0e10cSrcweir }; 135*cdf0e10cSrcweir 136*cdf0e10cSrcweir //______________________________________________________________________________ 137*cdf0e10cSrcweir BackendImpl::BackendImpl( 138*cdf0e10cSrcweir Sequence<Any> const & args, 139*cdf0e10cSrcweir Reference<XComponentContext> const & xComponentContext ) 140*cdf0e10cSrcweir : PackageRegistryBackend( args, xComponentContext ), 141*cdf0e10cSrcweir m_xHelpTypeInfo( new Package::TypeInfo( 142*cdf0e10cSrcweir OUSTR("application/vnd.sun.star.help"), 143*cdf0e10cSrcweir rtl::OUString(), 144*cdf0e10cSrcweir getResourceString(RID_STR_HELP), 145*cdf0e10cSrcweir RID_IMG_HELP, RID_IMG_HELP_HC ) ), 146*cdf0e10cSrcweir m_typeInfos( 1 ) 147*cdf0e10cSrcweir { 148*cdf0e10cSrcweir m_typeInfos[ 0 ] = m_xHelpTypeInfo; 149*cdf0e10cSrcweir if (!transientMode()) 150*cdf0e10cSrcweir { 151*cdf0e10cSrcweir OUString dbFile = makeURL(getCachePath(), OUSTR("backenddb.xml")); 152*cdf0e10cSrcweir m_backendDb.reset( 153*cdf0e10cSrcweir new HelpBackendDb(getComponentContext(), dbFile)); 154*cdf0e10cSrcweir 155*cdf0e10cSrcweir //clean up data folders which are no longer used. 156*cdf0e10cSrcweir //This must not be done in the same process where the help files 157*cdf0e10cSrcweir //are still registers. Only after revoking and restarting OOo the folders 158*cdf0e10cSrcweir //can be removed. This works now, because the extension manager is a singleton 159*cdf0e10cSrcweir //and the backends are only create once per process. 160*cdf0e10cSrcweir ::std::list<OUString> folders = m_backendDb->getAllDataUrls(); 161*cdf0e10cSrcweir deleteUnusedFolders(OUString(), folders); 162*cdf0e10cSrcweir } 163*cdf0e10cSrcweir } 164*cdf0e10cSrcweir 165*cdf0e10cSrcweir // XPackageRegistry 166*cdf0e10cSrcweir //______________________________________________________________________________ 167*cdf0e10cSrcweir Sequence< Reference<deployment::XPackageTypeInfo> > 168*cdf0e10cSrcweir BackendImpl::getSupportedPackageTypes() throw (RuntimeException) 169*cdf0e10cSrcweir { 170*cdf0e10cSrcweir return m_typeInfos; 171*cdf0e10cSrcweir } 172*cdf0e10cSrcweir 173*cdf0e10cSrcweir void BackendImpl::packageRemoved(OUString const & url, OUString const & /*mediaType*/) 174*cdf0e10cSrcweir throw (deployment::DeploymentException, 175*cdf0e10cSrcweir uno::RuntimeException) 176*cdf0e10cSrcweir { 177*cdf0e10cSrcweir if (m_backendDb.get()) 178*cdf0e10cSrcweir m_backendDb->removeEntry(url); 179*cdf0e10cSrcweir } 180*cdf0e10cSrcweir 181*cdf0e10cSrcweir // PackageRegistryBackend 182*cdf0e10cSrcweir //______________________________________________________________________________ 183*cdf0e10cSrcweir Reference<deployment::XPackage> BackendImpl::bindPackage_( 184*cdf0e10cSrcweir OUString const & url, OUString const & mediaType_, 185*cdf0e10cSrcweir sal_Bool bRemoved, OUString const & identifier, 186*cdf0e10cSrcweir Reference<XCommandEnvironment> const & xCmdEnv ) 187*cdf0e10cSrcweir { 188*cdf0e10cSrcweir // we don't support auto detection: 189*cdf0e10cSrcweir if (mediaType_.getLength() == 0) 190*cdf0e10cSrcweir throw lang::IllegalArgumentException( 191*cdf0e10cSrcweir StrCannotDetectMediaType::get() + url, 192*cdf0e10cSrcweir static_cast<OWeakObject *>(this), static_cast<sal_Int16>(-1) ); 193*cdf0e10cSrcweir 194*cdf0e10cSrcweir String type, subType; 195*cdf0e10cSrcweir INetContentTypeParameterList params; 196*cdf0e10cSrcweir if (INetContentTypes::parse( mediaType_, type, subType, ¶ms )) 197*cdf0e10cSrcweir { 198*cdf0e10cSrcweir if (type.EqualsIgnoreCaseAscii("application")) 199*cdf0e10cSrcweir { 200*cdf0e10cSrcweir OUString name; 201*cdf0e10cSrcweir if (!bRemoved) 202*cdf0e10cSrcweir { 203*cdf0e10cSrcweir ::ucbhelper::Content ucbContent( url, xCmdEnv ); 204*cdf0e10cSrcweir name = ucbContent.getPropertyValue( 205*cdf0e10cSrcweir StrTitle::get() ).get<OUString>(); 206*cdf0e10cSrcweir } 207*cdf0e10cSrcweir 208*cdf0e10cSrcweir if (subType.EqualsIgnoreCaseAscii( 209*cdf0e10cSrcweir "vnd.sun.star.help")) 210*cdf0e10cSrcweir { 211*cdf0e10cSrcweir return new PackageImpl( 212*cdf0e10cSrcweir this, url, name, m_xHelpTypeInfo, bRemoved, 213*cdf0e10cSrcweir identifier); 214*cdf0e10cSrcweir } 215*cdf0e10cSrcweir } 216*cdf0e10cSrcweir } 217*cdf0e10cSrcweir throw lang::IllegalArgumentException( 218*cdf0e10cSrcweir StrUnsupportedMediaType::get() + mediaType_, 219*cdf0e10cSrcweir static_cast<OWeakObject *>(this), 220*cdf0e10cSrcweir static_cast<sal_Int16>(-1) ); 221*cdf0e10cSrcweir } 222*cdf0e10cSrcweir 223*cdf0e10cSrcweir void BackendImpl::addDataToDb( 224*cdf0e10cSrcweir OUString const & url, HelpBackendDb::Data const & data) 225*cdf0e10cSrcweir { 226*cdf0e10cSrcweir if (m_backendDb.get()) 227*cdf0e10cSrcweir m_backendDb->addEntry(url, data); 228*cdf0e10cSrcweir } 229*cdf0e10cSrcweir 230*cdf0e10cSrcweir ::boost::optional<HelpBackendDb::Data> BackendImpl::readDataFromDb( 231*cdf0e10cSrcweir OUString const & url) 232*cdf0e10cSrcweir { 233*cdf0e10cSrcweir ::boost::optional<HelpBackendDb::Data> data; 234*cdf0e10cSrcweir if (m_backendDb.get()) 235*cdf0e10cSrcweir data = m_backendDb->getEntry(url); 236*cdf0e10cSrcweir return data; 237*cdf0e10cSrcweir } 238*cdf0e10cSrcweir 239*cdf0e10cSrcweir bool BackendImpl::hasActiveEntry(OUString const & url) 240*cdf0e10cSrcweir { 241*cdf0e10cSrcweir if (m_backendDb.get()) 242*cdf0e10cSrcweir return m_backendDb->hasActiveEntry(url); 243*cdf0e10cSrcweir return false; 244*cdf0e10cSrcweir } 245*cdf0e10cSrcweir 246*cdf0e10cSrcweir void BackendImpl::revokeEntryFromDb(OUString const & url) 247*cdf0e10cSrcweir { 248*cdf0e10cSrcweir if (m_backendDb.get()) 249*cdf0e10cSrcweir m_backendDb->revokeEntry(url); 250*cdf0e10cSrcweir } 251*cdf0e10cSrcweir 252*cdf0e10cSrcweir bool BackendImpl::activateEntry(OUString const & url) 253*cdf0e10cSrcweir { 254*cdf0e10cSrcweir if (m_backendDb.get()) 255*cdf0e10cSrcweir return m_backendDb->activateEntry(url); 256*cdf0e10cSrcweir return false; 257*cdf0e10cSrcweir } 258*cdf0e10cSrcweir 259*cdf0e10cSrcweir 260*cdf0e10cSrcweir //############################################################################## 261*cdf0e10cSrcweir BackendImpl::PackageImpl::PackageImpl( 262*cdf0e10cSrcweir ::rtl::Reference<PackageRegistryBackend> const & myBackend, 263*cdf0e10cSrcweir OUString const & url, OUString const & name, 264*cdf0e10cSrcweir Reference<deployment::XPackageTypeInfo> const & xPackageType, 265*cdf0e10cSrcweir bool bRemoved, OUString const & identifier) 266*cdf0e10cSrcweir : Package( myBackend, url, name, name, xPackageType, bRemoved, 267*cdf0e10cSrcweir identifier) 268*cdf0e10cSrcweir { 269*cdf0e10cSrcweir } 270*cdf0e10cSrcweir 271*cdf0e10cSrcweir // Package 272*cdf0e10cSrcweir BackendImpl * BackendImpl::PackageImpl::getMyBackend() const 273*cdf0e10cSrcweir { 274*cdf0e10cSrcweir BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get()); 275*cdf0e10cSrcweir if (NULL == pBackend) 276*cdf0e10cSrcweir { 277*cdf0e10cSrcweir //May throw a DisposedException 278*cdf0e10cSrcweir check(); 279*cdf0e10cSrcweir //We should never get here... 280*cdf0e10cSrcweir throw RuntimeException( 281*cdf0e10cSrcweir OUSTR("Failed to get the BackendImpl"), 282*cdf0e10cSrcweir static_cast<OWeakObject*>(const_cast<PackageImpl *>(this))); 283*cdf0e10cSrcweir } 284*cdf0e10cSrcweir return pBackend; 285*cdf0e10cSrcweir } 286*cdf0e10cSrcweir 287*cdf0e10cSrcweir bool BackendImpl::PackageImpl::extensionContainsCompiledHelp() 288*cdf0e10cSrcweir { 289*cdf0e10cSrcweir bool bCompiled = true; 290*cdf0e10cSrcweir rtl::OUString aExpandedHelpURL = dp_misc::expandUnoRcUrl(getURL()); 291*cdf0e10cSrcweir 292*cdf0e10cSrcweir ::osl::Directory helpFolder(aExpandedHelpURL); 293*cdf0e10cSrcweir if ( helpFolder.open() == ::osl::File::E_None) 294*cdf0e10cSrcweir { 295*cdf0e10cSrcweir //iterate over the contents of the help folder 296*cdf0e10cSrcweir //We assume that all folders withing the help folder contain language specific 297*cdf0e10cSrcweir //help files. If just one of them does not contain compiled help then this 298*cdf0e10cSrcweir //function returns false. 299*cdf0e10cSrcweir ::osl::DirectoryItem item; 300*cdf0e10cSrcweir ::osl::File::RC errorNext = ::osl::File::E_None; 301*cdf0e10cSrcweir while ((errorNext = helpFolder.getNextItem(item)) == ::osl::File::E_None) 302*cdf0e10cSrcweir { 303*cdf0e10cSrcweir //No find the language folders 304*cdf0e10cSrcweir ::osl::FileStatus stat(FileStatusMask_Type | FileStatusMask_FileName |FileStatusMask_FileURL); 305*cdf0e10cSrcweir if (item.getFileStatus(stat) == ::osl::File::E_None) 306*cdf0e10cSrcweir { 307*cdf0e10cSrcweir if (stat.getFileType() != ::osl::FileStatus::Directory) 308*cdf0e10cSrcweir continue; 309*cdf0e10cSrcweir 310*cdf0e10cSrcweir //look if there is the folder help.idxl in the language folder 311*cdf0e10cSrcweir OUString compUrl(stat.getFileURL() + OUSTR("/help.idxl")); 312*cdf0e10cSrcweir ::osl::Directory compiledFolder(compUrl); 313*cdf0e10cSrcweir if (compiledFolder.open() != ::osl::File::E_None) 314*cdf0e10cSrcweir { 315*cdf0e10cSrcweir bCompiled = false; 316*cdf0e10cSrcweir break; 317*cdf0e10cSrcweir } 318*cdf0e10cSrcweir } 319*cdf0e10cSrcweir else 320*cdf0e10cSrcweir { 321*cdf0e10cSrcweir //Error 322*cdf0e10cSrcweir OSL_ASSERT(0); 323*cdf0e10cSrcweir bCompiled = false; 324*cdf0e10cSrcweir break; 325*cdf0e10cSrcweir } 326*cdf0e10cSrcweir } 327*cdf0e10cSrcweir if (errorNext != ::osl::File::E_NOENT 328*cdf0e10cSrcweir && errorNext != ::osl::File::E_None) 329*cdf0e10cSrcweir { 330*cdf0e10cSrcweir //Error 331*cdf0e10cSrcweir OSL_ASSERT(0); 332*cdf0e10cSrcweir bCompiled = false; 333*cdf0e10cSrcweir } 334*cdf0e10cSrcweir } 335*cdf0e10cSrcweir return bCompiled; 336*cdf0e10cSrcweir } 337*cdf0e10cSrcweir 338*cdf0e10cSrcweir //______________________________________________________________________________ 339*cdf0e10cSrcweir beans::Optional< beans::Ambiguous<sal_Bool> > 340*cdf0e10cSrcweir BackendImpl::PackageImpl::isRegistered_( 341*cdf0e10cSrcweir ::osl::ResettableMutexGuard &, 342*cdf0e10cSrcweir ::rtl::Reference<AbortChannel> const &, 343*cdf0e10cSrcweir Reference<XCommandEnvironment> const & ) 344*cdf0e10cSrcweir { 345*cdf0e10cSrcweir BackendImpl * that = getMyBackend(); 346*cdf0e10cSrcweir 347*cdf0e10cSrcweir bool bReg = false; 348*cdf0e10cSrcweir if (that->hasActiveEntry(getURL())) 349*cdf0e10cSrcweir bReg = true; 350*cdf0e10cSrcweir 351*cdf0e10cSrcweir return beans::Optional< beans::Ambiguous<sal_Bool> >( true, beans::Ambiguous<sal_Bool>( bReg, false ) ); 352*cdf0e10cSrcweir } 353*cdf0e10cSrcweir 354*cdf0e10cSrcweir //______________________________________________________________________________ 355*cdf0e10cSrcweir void BackendImpl::PackageImpl::processPackage_( 356*cdf0e10cSrcweir ::osl::ResettableMutexGuard &, 357*cdf0e10cSrcweir bool doRegisterPackage, 358*cdf0e10cSrcweir bool /* startup */, 359*cdf0e10cSrcweir ::rtl::Reference<AbortChannel> const & abortChannel, 360*cdf0e10cSrcweir Reference<XCommandEnvironment> const & xCmdEnv ) 361*cdf0e10cSrcweir { 362*cdf0e10cSrcweir (void)doRegisterPackage; 363*cdf0e10cSrcweir (void)abortChannel; 364*cdf0e10cSrcweir (void)xCmdEnv; 365*cdf0e10cSrcweir 366*cdf0e10cSrcweir BackendImpl* that = getMyBackend(); 367*cdf0e10cSrcweir that->implProcessHelp( this, doRegisterPackage, xCmdEnv); 368*cdf0e10cSrcweir } 369*cdf0e10cSrcweir 370*cdf0e10cSrcweir beans::Optional< OUString > BackendImpl::PackageImpl::getRegistrationDataURL() 371*cdf0e10cSrcweir throw (deployment::ExtensionRemovedException, 372*cdf0e10cSrcweir css::uno::RuntimeException) 373*cdf0e10cSrcweir { 374*cdf0e10cSrcweir if (m_bRemoved) 375*cdf0e10cSrcweir throw deployment::ExtensionRemovedException(); 376*cdf0e10cSrcweir 377*cdf0e10cSrcweir ::boost::optional<HelpBackendDb::Data> data = 378*cdf0e10cSrcweir getMyBackend()->readDataFromDb(getURL()); 379*cdf0e10cSrcweir 380*cdf0e10cSrcweir if (data && getMyBackend()->hasActiveEntry(getURL())) 381*cdf0e10cSrcweir return beans::Optional<OUString>(true, data->dataUrl); 382*cdf0e10cSrcweir 383*cdf0e10cSrcweir return beans::Optional<OUString>(true, OUString()); 384*cdf0e10cSrcweir } 385*cdf0e10cSrcweir 386*cdf0e10cSrcweir 387*cdf0e10cSrcweir //############################################################################## 388*cdf0e10cSrcweir 389*cdf0e10cSrcweir static rtl::OUString aSlash( rtl::OUString::createFromAscii( "/" ) ); 390*cdf0e10cSrcweir static rtl::OUString aHelpStr( rtl::OUString::createFromAscii( "help" ) ); 391*cdf0e10cSrcweir 392*cdf0e10cSrcweir 393*cdf0e10cSrcweir void BackendImpl::implProcessHelp( 394*cdf0e10cSrcweir PackageImpl * package, bool doRegisterPackage, 395*cdf0e10cSrcweir Reference<ucb::XCommandEnvironment> const & xCmdEnv) 396*cdf0e10cSrcweir { 397*cdf0e10cSrcweir Reference< deployment::XPackage > xPackage(package); 398*cdf0e10cSrcweir OSL_ASSERT(xPackage.is()); 399*cdf0e10cSrcweir if (doRegisterPackage) 400*cdf0e10cSrcweir { 401*cdf0e10cSrcweir //revive already processed help if possible 402*cdf0e10cSrcweir if ( !activateEntry(xPackage->getURL())) 403*cdf0e10cSrcweir { 404*cdf0e10cSrcweir HelpBackendDb::Data data; 405*cdf0e10cSrcweir data.dataUrl = xPackage->getURL(); 406*cdf0e10cSrcweir if (!package->extensionContainsCompiledHelp()) 407*cdf0e10cSrcweir { 408*cdf0e10cSrcweir const OUString sHelpFolder = createFolder(OUString(), xCmdEnv); 409*cdf0e10cSrcweir data.dataUrl = sHelpFolder; 410*cdf0e10cSrcweir 411*cdf0e10cSrcweir Reference< ucb::XSimpleFileAccess > xSFA = getFileAccess(); 412*cdf0e10cSrcweir rtl::OUString aHelpURL = xPackage->getURL(); 413*cdf0e10cSrcweir rtl::OUString aExpandedHelpURL = dp_misc::expandUnoRcUrl( aHelpURL ); 414*cdf0e10cSrcweir rtl::OUString aName = xPackage->getName(); 415*cdf0e10cSrcweir if( !xSFA->isFolder( aExpandedHelpURL ) ) 416*cdf0e10cSrcweir { 417*cdf0e10cSrcweir rtl::OUString aErrStr = getResourceString( RID_STR_HELPPROCESSING_GENERAL_ERROR ); 418*cdf0e10cSrcweir aErrStr += rtl::OUString::createFromAscii( "No help folder" ); 419*cdf0e10cSrcweir OWeakObject* oWeakThis = static_cast<OWeakObject *>(this); 420*cdf0e10cSrcweir throw deployment::DeploymentException( rtl::OUString(), oWeakThis, 421*cdf0e10cSrcweir makeAny( uno::Exception( aErrStr, oWeakThis ) ) ); 422*cdf0e10cSrcweir } 423*cdf0e10cSrcweir 424*cdf0e10cSrcweir Reference<XComponentContext> const & xContext = getComponentContext(); 425*cdf0e10cSrcweir Reference< script::XInvocation > xInvocation; 426*cdf0e10cSrcweir if( xContext.is() ) 427*cdf0e10cSrcweir { 428*cdf0e10cSrcweir try 429*cdf0e10cSrcweir { 430*cdf0e10cSrcweir xInvocation = Reference< script::XInvocation >( 431*cdf0e10cSrcweir xContext->getServiceManager()->createInstanceWithContext( rtl::OUString::createFromAscii( 432*cdf0e10cSrcweir "com.sun.star.help.HelpIndexer" ), xContext ) , UNO_QUERY ); 433*cdf0e10cSrcweir } 434*cdf0e10cSrcweir catch (Exception &) 435*cdf0e10cSrcweir { 436*cdf0e10cSrcweir // i98680: Survive missing lucene 437*cdf0e10cSrcweir } 438*cdf0e10cSrcweir } 439*cdf0e10cSrcweir 440*cdf0e10cSrcweir // Scan languages 441*cdf0e10cSrcweir Sequence< rtl::OUString > aLanguageFolderSeq = xSFA->getFolderContents( aExpandedHelpURL, true ); 442*cdf0e10cSrcweir sal_Int32 nLangCount = aLanguageFolderSeq.getLength(); 443*cdf0e10cSrcweir const rtl::OUString* pSeq = aLanguageFolderSeq.getConstArray(); 444*cdf0e10cSrcweir for( sal_Int32 iLang = 0 ; iLang < nLangCount ; ++iLang ) 445*cdf0e10cSrcweir { 446*cdf0e10cSrcweir rtl::OUString aLangURL = pSeq[iLang]; 447*cdf0e10cSrcweir if( xSFA->isFolder( aLangURL ) ) 448*cdf0e10cSrcweir { 449*cdf0e10cSrcweir std::vector< rtl::OUString > aXhpFileVector; 450*cdf0e10cSrcweir 451*cdf0e10cSrcweir // calculate jar file URL 452*cdf0e10cSrcweir sal_Int32 indexStartSegment = aLangURL.lastIndexOf('/'); 453*cdf0e10cSrcweir // for example "/en" 454*cdf0e10cSrcweir OUString langFolderURLSegment( 455*cdf0e10cSrcweir aLangURL.copy( 456*cdf0e10cSrcweir indexStartSegment + 1, aLangURL.getLength() - indexStartSegment - 1)); 457*cdf0e10cSrcweir 458*cdf0e10cSrcweir //create the folder in the "temporary folder" 459*cdf0e10cSrcweir ::ucbhelper::Content langFolderContent; 460*cdf0e10cSrcweir const OUString langFolderDest = makeURL(sHelpFolder, langFolderURLSegment); 461*cdf0e10cSrcweir const OUString langFolderDestExpanded = ::dp_misc::expandUnoRcUrl(langFolderDest); 462*cdf0e10cSrcweir ::dp_misc::create_folder( 463*cdf0e10cSrcweir &langFolderContent, 464*cdf0e10cSrcweir langFolderDest, xCmdEnv); 465*cdf0e10cSrcweir 466*cdf0e10cSrcweir rtl::OUString aJarFile( 467*cdf0e10cSrcweir makeURL(sHelpFolder, langFolderURLSegment + aSlash + aHelpStr + 468*cdf0e10cSrcweir OUSTR(".jar"))); 469*cdf0e10cSrcweir aJarFile = ::dp_misc::expandUnoRcUrl(aJarFile); 470*cdf0e10cSrcweir 471*cdf0e10cSrcweir rtl::OUString aEncodedJarFilePath = rtl::Uri::encode( 472*cdf0e10cSrcweir aJarFile, rtl_UriCharClassPchar, 473*cdf0e10cSrcweir rtl_UriEncodeIgnoreEscapes, 474*cdf0e10cSrcweir RTL_TEXTENCODING_UTF8 ); 475*cdf0e10cSrcweir rtl::OUString aDestBasePath = rtl::OUString::createFromAscii( "vnd.sun.star.zip://" ); 476*cdf0e10cSrcweir aDestBasePath += aEncodedJarFilePath; 477*cdf0e10cSrcweir aDestBasePath += rtl::OUString::createFromAscii( "/" ); 478*cdf0e10cSrcweir 479*cdf0e10cSrcweir sal_Int32 nLenLangFolderURL = aLangURL.getLength() + 1; 480*cdf0e10cSrcweir 481*cdf0e10cSrcweir Sequence< rtl::OUString > aSubLangSeq = xSFA->getFolderContents( aLangURL, true ); 482*cdf0e10cSrcweir sal_Int32 nSubLangCount = aSubLangSeq.getLength(); 483*cdf0e10cSrcweir const rtl::OUString* pSubLangSeq = aSubLangSeq.getConstArray(); 484*cdf0e10cSrcweir for( sal_Int32 iSubLang = 0 ; iSubLang < nSubLangCount ; ++iSubLang ) 485*cdf0e10cSrcweir { 486*cdf0e10cSrcweir rtl::OUString aSubFolderURL = pSubLangSeq[iSubLang]; 487*cdf0e10cSrcweir if( !xSFA->isFolder( aSubFolderURL ) ) 488*cdf0e10cSrcweir continue; 489*cdf0e10cSrcweir 490*cdf0e10cSrcweir implCollectXhpFiles( aSubFolderURL, aXhpFileVector ); 491*cdf0e10cSrcweir 492*cdf0e10cSrcweir // Copy to package (later: move?) 493*cdf0e10cSrcweir rtl::OUString aDestPath = aDestBasePath; 494*cdf0e10cSrcweir rtl::OUString aPureFolderName = aSubFolderURL.copy( nLenLangFolderURL ); 495*cdf0e10cSrcweir aDestPath += aPureFolderName; 496*cdf0e10cSrcweir xSFA->copy( aSubFolderURL, aDestPath ); 497*cdf0e10cSrcweir } 498*cdf0e10cSrcweir 499*cdf0e10cSrcweir // Call compiler 500*cdf0e10cSrcweir sal_Int32 nXhpFileCount = aXhpFileVector.size(); 501*cdf0e10cSrcweir rtl::OUString* pXhpFiles = new rtl::OUString[nXhpFileCount]; 502*cdf0e10cSrcweir for( sal_Int32 iXhp = 0 ; iXhp < nXhpFileCount ; ++iXhp ) 503*cdf0e10cSrcweir { 504*cdf0e10cSrcweir rtl::OUString aXhpFile = aXhpFileVector[iXhp]; 505*cdf0e10cSrcweir rtl::OUString aXhpRelFile = aXhpFile.copy( nLenLangFolderURL ); 506*cdf0e10cSrcweir pXhpFiles[iXhp] = aXhpRelFile; 507*cdf0e10cSrcweir } 508*cdf0e10cSrcweir 509*cdf0e10cSrcweir rtl::OUString aOfficeHelpPath( SvtPathOptions().GetHelpPath() ); 510*cdf0e10cSrcweir rtl::OUString aOfficeHelpPathFileURL; 511*cdf0e10cSrcweir ::osl::File::getFileURLFromSystemPath( aOfficeHelpPath, aOfficeHelpPathFileURL ); 512*cdf0e10cSrcweir 513*cdf0e10cSrcweir HelpProcessingErrorInfo aErrorInfo; 514*cdf0e10cSrcweir bool bSuccess = compileExtensionHelp( 515*cdf0e10cSrcweir aOfficeHelpPathFileURL, aHelpStr, aLangURL, 516*cdf0e10cSrcweir nXhpFileCount, pXhpFiles, 517*cdf0e10cSrcweir langFolderDestExpanded, aErrorInfo ); 518*cdf0e10cSrcweir 519*cdf0e10cSrcweir if( bSuccess && xInvocation.is() ) 520*cdf0e10cSrcweir { 521*cdf0e10cSrcweir Sequence<uno::Any> aParamsSeq( 6 ); 522*cdf0e10cSrcweir 523*cdf0e10cSrcweir aParamsSeq[0] = uno::makeAny( rtl::OUString::createFromAscii( "-lang" ) ); 524*cdf0e10cSrcweir 525*cdf0e10cSrcweir rtl::OUString aLang; 526*cdf0e10cSrcweir sal_Int32 nLastSlash = aLangURL.lastIndexOf( '/' ); 527*cdf0e10cSrcweir if( nLastSlash != -1 ) 528*cdf0e10cSrcweir aLang = aLangURL.copy( nLastSlash + 1 ); 529*cdf0e10cSrcweir else 530*cdf0e10cSrcweir aLang = rtl::OUString::createFromAscii( "en" ); 531*cdf0e10cSrcweir aParamsSeq[1] = uno::makeAny( aLang ); 532*cdf0e10cSrcweir 533*cdf0e10cSrcweir aParamsSeq[2] = uno::makeAny( rtl::OUString::createFromAscii( "-mod" ) ); 534*cdf0e10cSrcweir aParamsSeq[3] = uno::makeAny( rtl::OUString::createFromAscii( "help" ) ); 535*cdf0e10cSrcweir 536*cdf0e10cSrcweir aParamsSeq[4] = uno::makeAny( rtl::OUString::createFromAscii( "-zipdir" ) ); 537*cdf0e10cSrcweir rtl::OUString aSystemPath; 538*cdf0e10cSrcweir osl::FileBase::getSystemPathFromFileURL( 539*cdf0e10cSrcweir langFolderDestExpanded, aSystemPath ); 540*cdf0e10cSrcweir aParamsSeq[5] = uno::makeAny( aSystemPath ); 541*cdf0e10cSrcweir 542*cdf0e10cSrcweir Sequence< sal_Int16 > aOutParamIndex; 543*cdf0e10cSrcweir Sequence< uno::Any > aOutParam; 544*cdf0e10cSrcweir uno::Any aRet = xInvocation->invoke( rtl::OUString::createFromAscii( "createIndex" ), 545*cdf0e10cSrcweir aParamsSeq, aOutParamIndex, aOutParam ); 546*cdf0e10cSrcweir } 547*cdf0e10cSrcweir 548*cdf0e10cSrcweir if( !bSuccess ) 549*cdf0e10cSrcweir { 550*cdf0e10cSrcweir sal_uInt16 nErrStrId = 0; 551*cdf0e10cSrcweir switch( aErrorInfo.m_eErrorClass ) 552*cdf0e10cSrcweir { 553*cdf0e10cSrcweir case HELPPROCESSING_GENERAL_ERROR: 554*cdf0e10cSrcweir case HELPPROCESSING_INTERNAL_ERROR: nErrStrId = RID_STR_HELPPROCESSING_GENERAL_ERROR; break; 555*cdf0e10cSrcweir case HELPPROCESSING_XMLPARSING_ERROR: nErrStrId = RID_STR_HELPPROCESSING_XMLPARSING_ERROR; break; 556*cdf0e10cSrcweir default: ; 557*cdf0e10cSrcweir }; 558*cdf0e10cSrcweir 559*cdf0e10cSrcweir rtl::OUString aErrStr; 560*cdf0e10cSrcweir if( nErrStrId != 0 ) 561*cdf0e10cSrcweir { 562*cdf0e10cSrcweir aErrStr = getResourceString( nErrStrId ); 563*cdf0e10cSrcweir 564*cdf0e10cSrcweir // Remoce CR/LF 565*cdf0e10cSrcweir rtl::OUString aErrMsg( aErrorInfo.m_aErrorMsg ); 566*cdf0e10cSrcweir sal_Unicode nCR = 13, nLF = 10; 567*cdf0e10cSrcweir sal_Int32 nSearchCR = aErrMsg.indexOf( nCR ); 568*cdf0e10cSrcweir sal_Int32 nSearchLF = aErrMsg.indexOf( nLF ); 569*cdf0e10cSrcweir sal_Int32 nCopy; 570*cdf0e10cSrcweir if( nSearchCR != -1 || nSearchLF != -1 ) 571*cdf0e10cSrcweir { 572*cdf0e10cSrcweir if( nSearchCR == -1 ) 573*cdf0e10cSrcweir nCopy = nSearchLF; 574*cdf0e10cSrcweir else if( nSearchLF == -1 ) 575*cdf0e10cSrcweir nCopy = nSearchCR; 576*cdf0e10cSrcweir else 577*cdf0e10cSrcweir nCopy = ( nSearchCR < nSearchLF ) ? nSearchCR : nSearchLF; 578*cdf0e10cSrcweir 579*cdf0e10cSrcweir aErrMsg = aErrMsg.copy( 0, nCopy ); 580*cdf0e10cSrcweir } 581*cdf0e10cSrcweir aErrStr += aErrMsg; 582*cdf0e10cSrcweir if( nErrStrId == RID_STR_HELPPROCESSING_XMLPARSING_ERROR && aErrorInfo.m_aXMLParsingFile.getLength() ) 583*cdf0e10cSrcweir { 584*cdf0e10cSrcweir aErrStr += rtl::OUString::createFromAscii( " in " ); 585*cdf0e10cSrcweir 586*cdf0e10cSrcweir rtl::OUString aDecodedFile = rtl::Uri::decode( aErrorInfo.m_aXMLParsingFile, 587*cdf0e10cSrcweir rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 ); 588*cdf0e10cSrcweir aErrStr += aDecodedFile; 589*cdf0e10cSrcweir if( aErrorInfo.m_nXMLParsingLine != -1 ) 590*cdf0e10cSrcweir { 591*cdf0e10cSrcweir aErrStr += rtl::OUString::createFromAscii( ", line " ); 592*cdf0e10cSrcweir aErrStr += ::rtl::OUString::valueOf( aErrorInfo.m_nXMLParsingLine ); 593*cdf0e10cSrcweir } 594*cdf0e10cSrcweir } 595*cdf0e10cSrcweir } 596*cdf0e10cSrcweir 597*cdf0e10cSrcweir OWeakObject* oWeakThis = static_cast<OWeakObject *>(this); 598*cdf0e10cSrcweir throw deployment::DeploymentException( rtl::OUString(), oWeakThis, 599*cdf0e10cSrcweir makeAny( uno::Exception( aErrStr, oWeakThis ) ) ); 600*cdf0e10cSrcweir } 601*cdf0e10cSrcweir } 602*cdf0e10cSrcweir } 603*cdf0e10cSrcweir } 604*cdf0e10cSrcweir //Writing the data entry replaces writing the flag file. If we got to this 605*cdf0e10cSrcweir //point the registration was successful. 606*cdf0e10cSrcweir addDataToDb(xPackage->getURL(), data); 607*cdf0e10cSrcweir } 608*cdf0e10cSrcweir } //if (doRegisterPackage) 609*cdf0e10cSrcweir else 610*cdf0e10cSrcweir { 611*cdf0e10cSrcweir revokeEntryFromDb(xPackage->getURL()); 612*cdf0e10cSrcweir } 613*cdf0e10cSrcweir } 614*cdf0e10cSrcweir 615*cdf0e10cSrcweir 616*cdf0e10cSrcweir void BackendImpl::implCollectXhpFiles( const rtl::OUString& aDir, 617*cdf0e10cSrcweir std::vector< rtl::OUString >& o_rXhpFileVector ) 618*cdf0e10cSrcweir { 619*cdf0e10cSrcweir Reference< ucb::XSimpleFileAccess > xSFA = getFileAccess(); 620*cdf0e10cSrcweir 621*cdf0e10cSrcweir // Scan xhp files recursively 622*cdf0e10cSrcweir Sequence< rtl::OUString > aSeq = xSFA->getFolderContents( aDir, true ); 623*cdf0e10cSrcweir sal_Int32 nCount = aSeq.getLength(); 624*cdf0e10cSrcweir const rtl::OUString* pSeq = aSeq.getConstArray(); 625*cdf0e10cSrcweir for( sal_Int32 i = 0 ; i < nCount ; ++i ) 626*cdf0e10cSrcweir { 627*cdf0e10cSrcweir rtl::OUString aURL = pSeq[i]; 628*cdf0e10cSrcweir if( xSFA->isFolder( aURL ) ) 629*cdf0e10cSrcweir { 630*cdf0e10cSrcweir implCollectXhpFiles( aURL, o_rXhpFileVector ); 631*cdf0e10cSrcweir } 632*cdf0e10cSrcweir else 633*cdf0e10cSrcweir { 634*cdf0e10cSrcweir sal_Int32 nLastDot = aURL.lastIndexOf( '.' ); 635*cdf0e10cSrcweir if( nLastDot != -1 ) 636*cdf0e10cSrcweir { 637*cdf0e10cSrcweir rtl::OUString aExt = aURL.copy( nLastDot + 1 ); 638*cdf0e10cSrcweir if( aExt.equalsIgnoreAsciiCase( rtl::OUString::createFromAscii( "xhp" ) ) ) 639*cdf0e10cSrcweir o_rXhpFileVector.push_back( aURL ); 640*cdf0e10cSrcweir } 641*cdf0e10cSrcweir } 642*cdf0e10cSrcweir } 643*cdf0e10cSrcweir } 644*cdf0e10cSrcweir 645*cdf0e10cSrcweir Reference< ucb::XSimpleFileAccess > BackendImpl::getFileAccess( void ) 646*cdf0e10cSrcweir { 647*cdf0e10cSrcweir if( !m_xSFA.is() ) 648*cdf0e10cSrcweir { 649*cdf0e10cSrcweir Reference<XComponentContext> const & xContext = getComponentContext(); 650*cdf0e10cSrcweir if( xContext.is() ) 651*cdf0e10cSrcweir { 652*cdf0e10cSrcweir m_xSFA = Reference< ucb::XSimpleFileAccess >( 653*cdf0e10cSrcweir xContext->getServiceManager()->createInstanceWithContext( 654*cdf0e10cSrcweir rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ), 655*cdf0e10cSrcweir xContext ), UNO_QUERY ); 656*cdf0e10cSrcweir } 657*cdf0e10cSrcweir if( !m_xSFA.is() ) 658*cdf0e10cSrcweir { 659*cdf0e10cSrcweir throw RuntimeException( 660*cdf0e10cSrcweir ::rtl::OUString::createFromAscii( 661*cdf0e10cSrcweir "dp_registry::backend::help::BackendImpl::getFileAccess(), " 662*cdf0e10cSrcweir "could not instatiate SimpleFileAccess." ), 663*cdf0e10cSrcweir Reference< XInterface >() ); 664*cdf0e10cSrcweir } 665*cdf0e10cSrcweir } 666*cdf0e10cSrcweir return m_xSFA; 667*cdf0e10cSrcweir } 668*cdf0e10cSrcweir 669*cdf0e10cSrcweir } // anon namespace 670*cdf0e10cSrcweir 671*cdf0e10cSrcweir namespace sdecl = comphelper::service_decl; 672*cdf0e10cSrcweir sdecl::class_<BackendImpl, sdecl::with_args<true> > serviceBI; 673*cdf0e10cSrcweir extern sdecl::ServiceDecl const serviceDecl( 674*cdf0e10cSrcweir serviceBI, 675*cdf0e10cSrcweir "com.sun.star.comp.deployment.help.PackageRegistryBackend", 676*cdf0e10cSrcweir BACKEND_SERVICE_NAME ); 677*cdf0e10cSrcweir 678*cdf0e10cSrcweir } // namespace help 679*cdf0e10cSrcweir } // namespace backend 680*cdf0e10cSrcweir } // namespace dp_registry 681*cdf0e10cSrcweir 682