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