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