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