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