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, &params ))
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