merge the formfield patch from ooo-build
[ooovba.git] / desktop / source / deployment / registry / help / dp_help.cxx
blob8ef0a7141ae3ad6acdb28996da90bc67b4ee7e36
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: dp_help.cxx,v $
10 * $Revision: 1.5 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_desktop.hxx"
34 #include "dp_help.hrc"
35 #include "dp_backend.h"
36 #include "dp_ucb.h"
37 #include "rtl/uri.hxx"
38 #include "osl/file.hxx"
39 #include "ucbhelper/content.hxx"
40 #include "comphelper/servicedecl.hxx"
41 #include "svtools/inettype.hxx"
43 #include <transex3/compilehelp.hxx>
44 #include <com/sun/star/ucb/XSimpleFileAccess.hpp>
45 #include <com/sun/star/util/XMacroExpander.hpp>
46 #include <com/sun/star/uri/XUriReferenceFactory.hpp>
47 #include <com/sun/star/uri/XVndSunStarExpandUrl.hpp>
48 #include <com/sun/star/script/XInvocation.hpp>
50 using namespace ::dp_misc;
51 using namespace ::com::sun::star;
52 using namespace ::com::sun::star::uno;
53 using namespace ::com::sun::star::ucb;
54 using ::rtl::OUString;
56 namespace dp_registry {
57 namespace backend {
58 namespace help {
59 namespace {
61 //==============================================================================
62 class BackendImpl : public ::dp_registry::backend::PackageRegistryBackend
64 class PackageImpl : public ::dp_registry::backend::Package
66 BackendImpl * getMyBackend() const;
68 // Package
69 virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_(
70 ::osl::ResettableMutexGuard & guard,
71 ::rtl::Reference<AbortChannel> const & abortChannel,
72 Reference<XCommandEnvironment> const & xCmdEnv );
73 virtual void processPackage_(
74 ::osl::ResettableMutexGuard & guard,
75 bool registerPackage,
76 ::rtl::Reference<AbortChannel> const & abortChannel,
77 Reference<XCommandEnvironment> const & xCmdEnv );
79 public:
80 inline PackageImpl(
81 ::rtl::Reference<PackageRegistryBackend> const & myBackend,
82 OUString const & url, OUString const & name,
83 Reference<deployment::XPackageTypeInfo> const & xPackageType )
84 : Package( myBackend, url, name, name, xPackageType )
87 friend class PackageImpl;
89 // PackageRegistryBackend
90 virtual Reference<deployment::XPackage> bindPackage_(
91 OUString const & url, OUString const & mediaType,
92 Reference<XCommandEnvironment> const & xCmdEnv );
94 void implProcessHelp( Reference< deployment::XPackage > xPackage, bool doRegisterPackage );
95 void implCollectXhpFiles( const rtl::OUString& aDir,
96 std::vector< rtl::OUString >& o_rXhpFileVector );
97 rtl::OUString getFlagFileURL( Reference< deployment::XPackage > xPackage, const char* pFlagStr );
98 rtl::OUString getRegisteredFlagFileURL( Reference< deployment::XPackage > xPackage );
99 rtl::OUString getCompiledFlagFileURL( Reference< deployment::XPackage > xPackage );
100 rtl::OUString expandURL( const rtl::OUString& aURL );
101 Reference< ucb::XSimpleFileAccess > getFileAccess( void );
102 Reference< ucb::XSimpleFileAccess > m_xSFA;
104 const Reference<deployment::XPackageTypeInfo> m_xHelpTypeInfo;
105 Sequence< Reference<deployment::XPackageTypeInfo> > m_typeInfos;
107 public:
108 BackendImpl( Sequence<Any> const & args,
109 Reference<XComponentContext> const & xComponentContext );
111 // XPackageRegistry
112 virtual Sequence< Reference<deployment::XPackageTypeInfo> > SAL_CALL
113 getSupportedPackageTypes() throw (RuntimeException);
116 //______________________________________________________________________________
117 BackendImpl::BackendImpl(
118 Sequence<Any> const & args,
119 Reference<XComponentContext> const & xComponentContext )
120 : PackageRegistryBackend( args, xComponentContext ),
121 m_xHelpTypeInfo( new Package::TypeInfo(
122 OUSTR("application/vnd.sun.star.help"),
123 rtl::OUString(),
124 getResourceString(RID_STR_HELP),
125 RID_IMG_HELP, RID_IMG_HELP_HC ) ),
126 m_typeInfos( 1 )
128 m_typeInfos[ 0 ] = m_xHelpTypeInfo;
131 // XPackageRegistry
132 //______________________________________________________________________________
133 Sequence< Reference<deployment::XPackageTypeInfo> >
134 BackendImpl::getSupportedPackageTypes() throw (RuntimeException)
136 return m_typeInfos;
139 // PackageRegistryBackend
140 //______________________________________________________________________________
141 Reference<deployment::XPackage> BackendImpl::bindPackage_(
142 OUString const & url, OUString const & mediaType_,
143 Reference<XCommandEnvironment> const & xCmdEnv )
145 // we don't support auto detection:
146 if (mediaType_.getLength() == 0)
147 throw lang::IllegalArgumentException(
148 StrCannotDetectMediaType::get() + url,
149 static_cast<OWeakObject *>(this), static_cast<sal_Int16>(-1) );
151 String type, subType;
152 INetContentTypeParameterList params;
153 if (INetContentTypes::parse( mediaType_, type, subType, &params ))
155 if (type.EqualsIgnoreCaseAscii("application"))
157 ::ucbhelper::Content ucbContent( url, xCmdEnv );
158 if (subType.EqualsIgnoreCaseAscii(
159 "vnd.sun.star.help"))
161 return new PackageImpl( this, url,
162 ucbContent.getPropertyValue( StrTitle::get() ).get<OUString>(), m_xHelpTypeInfo );
166 throw lang::IllegalArgumentException(
167 StrUnsupportedMediaType::get() + mediaType_,
168 static_cast<OWeakObject *>(this),
169 static_cast<sal_Int16>(-1) );
173 //##############################################################################
175 // Package
176 BackendImpl * BackendImpl::PackageImpl::getMyBackend() const
178 BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get());
179 if (NULL == pBackend)
181 //May throw a DisposedException
182 check();
183 //We should never get here...
184 throw RuntimeException(
185 OUSTR("Failed to get the BackendImpl"),
186 static_cast<OWeakObject*>(const_cast<PackageImpl *>(this)));
188 return pBackend;
191 //______________________________________________________________________________
192 beans::Optional< beans::Ambiguous<sal_Bool> >
193 BackendImpl::PackageImpl::isRegistered_(
194 ::osl::ResettableMutexGuard &,
195 ::rtl::Reference<AbortChannel> const &,
196 Reference<XCommandEnvironment> const & )
198 BackendImpl * that = getMyBackend();
199 Reference< deployment::XPackage > xThisPackage( this );
200 rtl::OUString aRegisteredFlagFile = that->getRegisteredFlagFileURL( xThisPackage );
202 Reference< ucb::XSimpleFileAccess > xSFA = that->getFileAccess();
203 bool bReg = xSFA->exists( aRegisteredFlagFile );
205 return beans::Optional< beans::Ambiguous<sal_Bool> >( true, beans::Ambiguous<sal_Bool>( bReg, false ) );
208 //______________________________________________________________________________
209 void BackendImpl::PackageImpl::processPackage_(
210 ::osl::ResettableMutexGuard &,
211 bool doRegisterPackage,
212 ::rtl::Reference<AbortChannel> const & abortChannel,
213 Reference<XCommandEnvironment> const & xCmdEnv )
215 (void)doRegisterPackage;
216 (void)abortChannel;
217 (void)xCmdEnv;
219 BackendImpl* that = getMyBackend();
220 Reference< deployment::XPackage > xThisPackage( this );
221 that->implProcessHelp( xThisPackage, doRegisterPackage );
224 //##############################################################################
226 static rtl::OUString aSlash( rtl::OUString::createFromAscii( "/" ) );
227 static rtl::OUString aHelpStr( rtl::OUString::createFromAscii( "help" ) );
229 void BackendImpl::implProcessHelp
230 ( Reference< deployment::XPackage > xPackage, bool doRegisterPackage )
232 if( !xPackage.is() )
233 return;
235 Reference< ucb::XSimpleFileAccess > xSFA = getFileAccess();
237 rtl::OUString aRegisteredFlagFile = getRegisteredFlagFileURL( xPackage );
238 if( !doRegisterPackage )
240 if( xSFA->exists( aRegisteredFlagFile ) )
241 xSFA->kill( aRegisteredFlagFile );
242 return;
245 bool bCompile = true;
246 rtl::OUString aCompiledFlagFile = getCompiledFlagFileURL( xPackage );
247 if( xSFA->exists( aCompiledFlagFile ) )
248 bCompile = false;
250 if( bCompile )
252 rtl::OUString aHelpURL = xPackage->getURL();
253 rtl::OUString aExpandedHelpURL = expandURL( aHelpURL );
254 rtl::OUString aName = xPackage->getName();
255 if( !xSFA->isFolder( aExpandedHelpURL ) )
257 rtl::OUString aErrStr = getResourceString( RID_STR_HELPPROCESSING_GENERAL_ERROR );
258 aErrStr += rtl::OUString::createFromAscii( "No help folder" );
259 OWeakObject* oWeakThis = static_cast<OWeakObject *>(this);
260 throw deployment::DeploymentException( rtl::OUString(), oWeakThis,
261 makeAny( uno::Exception( aErrStr, oWeakThis ) ) );
264 Reference<XComponentContext> const & xContext = getComponentContext();
265 Reference< script::XInvocation > xInvocation;
266 if( xContext.is() )
270 xInvocation = Reference< script::XInvocation >(
271 xContext->getServiceManager()->createInstanceWithContext( rtl::OUString::createFromAscii(
272 "com.sun.star.help.HelpIndexer" ), xContext ) , UNO_QUERY );
274 catch (Exception &)
276 // i98680: Survive missing lucene
280 // Scan languages
281 Sequence< rtl::OUString > aLanguageFolderSeq = xSFA->getFolderContents( aExpandedHelpURL, true );
282 sal_Int32 nLangCount = aLanguageFolderSeq.getLength();
283 const rtl::OUString* pSeq = aLanguageFolderSeq.getConstArray();
284 for( sal_Int32 iLang = 0 ; iLang < nLangCount ; ++iLang )
286 rtl::OUString aLangURL = pSeq[iLang];
287 if( xSFA->isFolder( aLangURL ) )
289 std::vector< rtl::OUString > aXhpFileVector;
291 // Delete (old) files in any case to allow compiler to be started every time
292 rtl::OUString aLangWithPureNameURL( aLangURL );
293 aLangWithPureNameURL += aSlash;
294 aLangWithPureNameURL += aHelpStr;
295 rtl::OUString aDbFile( aLangWithPureNameURL );
296 aDbFile += rtl::OUString::createFromAscii( ".db" );
297 if( xSFA->exists( aDbFile ) )
298 xSFA->kill( aDbFile );
299 rtl::OUString aHtFile( aLangWithPureNameURL );
300 aHtFile += rtl::OUString::createFromAscii( ".ht" );
301 if( xSFA->exists( aHtFile ) )
302 xSFA->kill( aHtFile );
303 rtl::OUString aKeyFile( aLangWithPureNameURL );
304 aKeyFile += rtl::OUString::createFromAscii( ".key" );
305 if( xSFA->exists( aKeyFile ) )
306 xSFA->kill( aKeyFile );
308 // calculate jar file URL
309 rtl::OUString aJarFile( aLangURL );
310 aJarFile += aSlash;
311 aJarFile += aHelpStr;
312 aJarFile += rtl::OUString::createFromAscii( ".jar" );
313 // remove in any case to clean up
314 if( xSFA->exists( aJarFile ) )
315 xSFA->kill( aJarFile );
317 rtl::OUString aEncodedJarFilePath = rtl::Uri::encode( aJarFile,
318 rtl_UriCharClassPchar, rtl_UriEncodeIgnoreEscapes, RTL_TEXTENCODING_UTF8 );
319 rtl::OUString aDestBasePath = rtl::OUString::createFromAscii( "vnd.sun.star.pkg://" );
320 aDestBasePath += aEncodedJarFilePath;
321 aDestBasePath += rtl::OUString::createFromAscii( "/" );
323 sal_Int32 nLenLangFolderURL = aLangURL.getLength() + 1;
325 Sequence< rtl::OUString > aSubLangSeq = xSFA->getFolderContents( aLangURL, true );
326 sal_Int32 nSubLangCount = aSubLangSeq.getLength();
327 const rtl::OUString* pSubLangSeq = aSubLangSeq.getConstArray();
328 for( sal_Int32 iSubLang = 0 ; iSubLang < nSubLangCount ; ++iSubLang )
330 rtl::OUString aSubFolderURL = pSubLangSeq[iSubLang];
331 if( !xSFA->isFolder( aSubFolderURL ) )
332 continue;
334 implCollectXhpFiles( aSubFolderURL, aXhpFileVector );
336 // Copy to package (later: move?)
337 rtl::OUString aDestPath = aDestBasePath;
338 rtl::OUString aPureFolderName = aSubFolderURL.copy( nLenLangFolderURL );
339 aDestPath += aPureFolderName;
340 xSFA->copy( aSubFolderURL, aDestPath );
343 // Call compiler
344 sal_Int32 nXhpFileCount = aXhpFileVector.size();
345 rtl::OUString* pXhpFiles = new rtl::OUString[nXhpFileCount];
346 for( sal_Int32 iXhp = 0 ; iXhp < nXhpFileCount ; ++iXhp )
348 rtl::OUString aXhpFile = aXhpFileVector[iXhp];
349 rtl::OUString aXhpRelFile = aXhpFile.copy( nLenLangFolderURL );
350 pXhpFiles[iXhp] = aXhpRelFile;
353 HelpProcessingErrorInfo aErrorInfo;
354 bool bSuccess = compileExtensionHelp( aHelpStr, aLangURL,
355 nXhpFileCount, pXhpFiles, aErrorInfo );
357 if( bSuccess && xInvocation.is() )
359 Sequence<uno::Any> aParamsSeq( 6 );
361 aParamsSeq[0] = uno::makeAny( rtl::OUString::createFromAscii( "-lang" ) );
363 rtl::OUString aLang;
364 sal_Int32 nLastSlash = aLangURL.lastIndexOf( '/' );
365 if( nLastSlash != -1 )
366 aLang = aLangURL.copy( nLastSlash + 1 );
367 else
368 aLang = rtl::OUString::createFromAscii( "en" );
369 aParamsSeq[1] = uno::makeAny( aLang );
371 aParamsSeq[2] = uno::makeAny( rtl::OUString::createFromAscii( "-mod" ) );
372 aParamsSeq[3] = uno::makeAny( rtl::OUString::createFromAscii( "help" ) );
374 aParamsSeq[4] = uno::makeAny( rtl::OUString::createFromAscii( "-zipdir" ) );
375 rtl::OUString aSystemPath;
376 osl::FileBase::getSystemPathFromFileURL( aLangURL, aSystemPath );
377 aParamsSeq[5] = uno::makeAny( aSystemPath );
379 Sequence< sal_Int16 > aOutParamIndex;
380 Sequence< uno::Any > aOutParam;
381 uno::Any aRet = xInvocation->invoke( rtl::OUString::createFromAscii( "createIndex" ),
382 aParamsSeq, aOutParamIndex, aOutParam );
385 if( !bSuccess )
387 USHORT nErrStrId = 0;
388 switch( aErrorInfo.m_eErrorClass )
390 case HELPPROCESSING_GENERAL_ERROR:
391 case HELPPROCESSING_INTERNAL_ERROR: nErrStrId = RID_STR_HELPPROCESSING_GENERAL_ERROR; break;
392 case HELPPROCESSING_XMLPARSING_ERROR: nErrStrId = RID_STR_HELPPROCESSING_XMLPARSING_ERROR; break;
393 default: ;
396 rtl::OUString aErrStr;
397 if( nErrStrId != 0 )
399 aErrStr = getResourceString( nErrStrId );
401 // Remoce CR/LF
402 rtl::OUString aErrMsg( aErrorInfo.m_aErrorMsg );
403 sal_Unicode nCR = 13, nLF = 10;
404 sal_Int32 nSearchCR = aErrMsg.indexOf( nCR );
405 sal_Int32 nSearchLF = aErrMsg.indexOf( nLF );
406 sal_Int32 nCopy;
407 if( nSearchCR != -1 || nSearchLF != -1 )
409 if( nSearchCR == -1 )
410 nCopy = nSearchLF;
411 else if( nSearchLF == -1 )
412 nCopy = nSearchCR;
413 else
414 nCopy = ( nSearchCR < nSearchLF ) ? nSearchCR : nSearchLF;
416 aErrMsg = aErrMsg.copy( 0, nCopy );
418 aErrStr += aErrMsg;
419 if( nErrStrId == RID_STR_HELPPROCESSING_XMLPARSING_ERROR && aErrorInfo.m_aXMLParsingFile.getLength() )
421 aErrStr += rtl::OUString::createFromAscii( " in " );
423 rtl::OUString aDecodedFile = rtl::Uri::decode( aErrorInfo.m_aXMLParsingFile,
424 rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 );
425 aErrStr += aDecodedFile;
426 if( aErrorInfo.m_nXMLParsingLine != -1 )
428 aErrStr += rtl::OUString::createFromAscii( ", line " );
429 aErrStr += ::rtl::OUString::valueOf( aErrorInfo.m_nXMLParsingLine );
434 OWeakObject* oWeakThis = static_cast<OWeakObject *>(this);
435 throw deployment::DeploymentException( rtl::OUString(), oWeakThis,
436 makeAny( uno::Exception( aErrStr, oWeakThis ) ) );
441 // Write compiled flag file (this code is only reached in case of success)
442 Reference< io::XOutputStream > xOutputStream = xSFA->openFileWrite( aCompiledFlagFile );
443 if( xOutputStream.is() )
444 xOutputStream->closeOutput();
446 } // if( bCompile )
448 // Write registered flag file (this code is only reached in case of success)
449 if( !xSFA->exists( aRegisteredFlagFile ) )
451 Reference< io::XOutputStream > xOutputStream = xSFA->openFileWrite( aRegisteredFlagFile );
452 if( xOutputStream.is() )
453 xOutputStream->closeOutput();
457 rtl::OUString BackendImpl::getFlagFileURL( Reference< deployment::XPackage > xPackage, const char* pFlagStr )
459 rtl::OUString aRetURL;
460 if( !xPackage.is() )
461 return aRetURL;
462 rtl::OUString aHelpURL = xPackage->getURL();
463 aRetURL = expandURL( aHelpURL );
464 aRetURL += rtl::OUString::createFromAscii( pFlagStr );
465 return aRetURL;
468 rtl::OUString BackendImpl::getRegisteredFlagFileURL( Reference< deployment::XPackage > xPackage )
470 return getFlagFileURL( xPackage, "/RegisteredFlag" );
473 rtl::OUString BackendImpl::getCompiledFlagFileURL( Reference< deployment::XPackage > xPackage )
475 return getFlagFileURL( xPackage, "/CompiledFlag" );
478 rtl::OUString BackendImpl::expandURL( const rtl::OUString& aURL )
480 static Reference< util::XMacroExpander > xMacroExpander;
481 static Reference< uri::XUriReferenceFactory > xFac;
483 if( !xMacroExpander.is() || !xFac.is() )
485 Reference<XComponentContext> const & xContext = getComponentContext();
486 if( xContext.is() )
488 xFac = Reference< uri::XUriReferenceFactory >(
489 xContext->getServiceManager()->createInstanceWithContext( rtl::OUString::createFromAscii(
490 "com.sun.star.uri.UriReferenceFactory"), xContext ) , UNO_QUERY );
492 if( !xFac.is() )
494 throw RuntimeException(
495 ::rtl::OUString::createFromAscii(
496 "dp_registry::backend::help::BackendImpl::expandURL(), "
497 "could not instatiate UriReferenceFactory." ),
498 Reference< XInterface >() );
501 xMacroExpander = Reference< util::XMacroExpander >(
502 xContext->getValueByName(
503 ::rtl::OUString::createFromAscii( "/singletons/com.sun.star.util.theMacroExpander" ) ),
504 UNO_QUERY_THROW );
507 rtl::OUString aRetURL = aURL;
508 if( xMacroExpander.is() )
510 Reference< uri::XUriReference > uriRef;
511 for (;;)
513 uriRef = Reference< uri::XUriReference >( xFac->parse( aRetURL ), UNO_QUERY );
514 if ( uriRef.is() )
516 Reference < uri::XVndSunStarExpandUrl > sxUri( uriRef, UNO_QUERY );
517 if( !sxUri.is() )
518 break;
520 aRetURL = sxUri->expand( xMacroExpander );
524 return aRetURL;
527 void BackendImpl::implCollectXhpFiles( const rtl::OUString& aDir,
528 std::vector< rtl::OUString >& o_rXhpFileVector )
530 Reference< ucb::XSimpleFileAccess > xSFA = getFileAccess();
532 // Scan xhp files recursively
533 Sequence< rtl::OUString > aSeq = xSFA->getFolderContents( aDir, true );
534 sal_Int32 nCount = aSeq.getLength();
535 const rtl::OUString* pSeq = aSeq.getConstArray();
536 for( sal_Int32 i = 0 ; i < nCount ; ++i )
538 rtl::OUString aURL = pSeq[i];
539 if( xSFA->isFolder( aURL ) )
541 implCollectXhpFiles( aURL, o_rXhpFileVector );
543 else
545 sal_Int32 nLastDot = aURL.lastIndexOf( '.' );
546 if( nLastDot != -1 )
548 rtl::OUString aExt = aURL.copy( nLastDot + 1 );
549 if( aExt.equalsIgnoreAsciiCase( rtl::OUString::createFromAscii( "xhp" ) ) )
550 o_rXhpFileVector.push_back( aURL );
556 Reference< ucb::XSimpleFileAccess > BackendImpl::getFileAccess( void )
558 if( !m_xSFA.is() )
560 Reference<XComponentContext> const & xContext = getComponentContext();
561 if( xContext.is() )
563 m_xSFA = Reference< ucb::XSimpleFileAccess >(
564 xContext->getServiceManager()->createInstanceWithContext(
565 rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ),
566 xContext ), UNO_QUERY );
568 if( !m_xSFA.is() )
570 throw RuntimeException(
571 ::rtl::OUString::createFromAscii(
572 "dp_registry::backend::help::BackendImpl::getFileAccess(), "
573 "could not instatiate SimpleFileAccess." ),
574 Reference< XInterface >() );
577 return m_xSFA;
580 } // anon namespace
582 namespace sdecl = comphelper::service_decl;
583 sdecl::class_<BackendImpl, sdecl::with_args<true> > serviceBI;
584 extern sdecl::ServiceDecl const serviceDecl(
585 serviceBI,
586 "com.sun.star.comp.deployment.help.PackageRegistryBackend",
587 BACKEND_SERVICE_NAME );
589 } // namespace help
590 } // namespace backend
591 } // namespace dp_registry