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