diff options
author | Ivo Hinkelmann <ihi@openoffice.org> | 2007-11-19 12:00:39 +0000 |
---|---|---|
committer | Ivo Hinkelmann <ihi@openoffice.org> | 2007-11-19 12:00:39 +0000 |
commit | d35d8cb4bb36acd71648a36dfb526340e8d3d4de (patch) | |
tree | 221a5c6470941b608c006afa3b5e45131c0cc77f /xmlhelp/source | |
parent | f4e30879471b26b3d608b776b803f28338301c15 (diff) |
INTEGRATION: CWS ab38 (1.48.22); FILE MERGED
2007/11/06 14:56:05 ab 1.48.22.1: #i20164# Extension help support
Diffstat (limited to 'xmlhelp/source')
-rw-r--r-- | xmlhelp/source/cxxhelp/provider/databases.cxx | 942 |
1 files changed, 800 insertions, 142 deletions
diff --git a/xmlhelp/source/cxxhelp/provider/databases.cxx b/xmlhelp/source/cxxhelp/provider/databases.cxx index e69507e01dd0..ea191b651550 100644 --- a/xmlhelp/source/cxxhelp/provider/databases.cxx +++ b/xmlhelp/source/cxxhelp/provider/databases.cxx @@ -4,9 +4,9 @@ * * $RCSfile: databases.cxx,v $ * - * $Revision: 1.48 $ + * $Revision: 1.49 $ * - * last change: $Author: vg $ $Date: 2006-11-01 14:07:23 $ + * last change: $Author: ihi $ $Date: 2007-11-19 13:00:39 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -72,14 +72,81 @@ #include "inputstream.hxx" #include <algorithm> +// Extensible help +#include "com/sun/star/deployment/thePackageManagerFactory.hpp" +#include <comphelper/processfactory.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/ucb/XCommandEnvironment.hpp> +#include <com/sun/star/beans/Optional.hpp> +#include <com/sun/star/frame/XConfigManager.hpp> +#include <com/sun/star/util/XMacroExpander.hpp> +#include <com/sun/star/uri/XUriReferenceFactory.hpp> +#include <com/sun/star/uri/XVndSunStarExpandUrl.hpp> + +#include <xmlhelp/compilehelp.hxx> + using namespace chelp; using namespace berkeleydbproxy; +using namespace com::sun::star; using namespace com::sun::star::uno; using namespace com::sun::star::io; using namespace com::sun::star::container; using namespace com::sun::star::i18n; using namespace com::sun::star::lang; +using namespace com::sun::star::deployment; +using namespace com::sun::star::beans; + + +static rtl::OUString aSlash( rtl::OUString::createFromAscii( "/" ) ); +static rtl::OUString aHelpFilesBaseName( rtl::OUString::createFromAscii( "help" ) ); +static rtl::OUString aEnglishFallbackLang( rtl::OUString::createFromAscii( "en" ) ); +static rtl::OUString aHelpMediaType( rtl::OUString::createFromAscii( "application/vnd.sun.star.help" ) ); + +rtl::OUString Databases::expandURL( const rtl::OUString& aURL ) +{ + static Reference< util::XMacroExpander > xMacroExpander; + static Reference< uri::XUriReferenceFactory > xFac; + osl::MutexGuard aGuard( m_aMutex ); + + if( !xMacroExpander.is() || !xFac.is() ) + { + xFac = Reference< uri::XUriReferenceFactory >( + m_xSMgr->createInstanceWithContext( rtl::OUString::createFromAscii( + "com.sun.star.uri.UriReferenceFactory"), m_xContext ) , UNO_QUERY ); + if( !xFac.is() ) + { + throw RuntimeException( + ::rtl::OUString::createFromAscii( "Databases::expand(), could not instatiate UriReferenceFactory." ), + Reference< XInterface >() ); + } + + xMacroExpander = Reference< util::XMacroExpander >( + m_xContext->getValueByName( + ::rtl::OUString::createFromAscii( "/singletons/com.sun.star.util.theMacroExpander" ) ), + UNO_QUERY_THROW ); + } + + rtl::OUString aRetURL = aURL; + if( xMacroExpander.is() ) + { + Reference< uri::XUriReference > uriRef; + for (;;) + { + uriRef = Reference< uri::XUriReference >( xFac->parse( aRetURL ), UNO_QUERY ); + if ( uriRef.is() ) + { + Reference < uri::XVndSunStarExpandUrl > sxUri( uriRef, UNO_QUERY ); + if( !sxUri.is() ) + break; + + aRetURL = sxUri->expand( xMacroExpander ); + } + } + } + return aRetURL; +} Databases::Databases( sal_Bool showBasic, const rtl::OUString& instPath, @@ -90,8 +157,8 @@ Databases::Databases( sal_Bool showBasic, const rtl::OUString& vendorVersion, const rtl::OUString& vendorShort, const rtl::OUString& styleSheet, - com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > xSMgr ) - : m_xSMgr( xSMgr ), + Reference< uno::XComponentContext > xContext ) + : m_xContext( xContext ), m_bShowBasic(showBasic), m_nErrorDocLength( 0 ), m_pErrorDoc( 0 ), @@ -108,6 +175,8 @@ Databases::Databases( sal_Bool showBasic, m_aImagesZipPaths( imagesZipPaths ), m_nSymbolsStyle( 0 ) { + m_xSMgr = Reference< XMultiComponentFactory >( m_xContext->getServiceManager(), UNO_QUERY ); + m_vAdd[0] = 12; m_vAdd[1] = 15; m_vAdd[2] = 11; @@ -127,6 +196,33 @@ Databases::Databases( sal_Bool showBasic, setInstallPath( instPath ); } +void Databases::implCollectXhpFiles( const rtl::OUString& aDir, + std::vector< rtl::OUString >& o_rXhpFileVector, + Reference< ucb::XSimpleFileAccess > xSFA ) +{ + // Scan xhp files recursively + Sequence< rtl::OUString > aSeq = xSFA->getFolderContents( aDir, true ); + sal_Int32 nCount = aSeq.getLength(); + const rtl::OUString* pSeq = aSeq.getConstArray(); + for( sal_Int32 i = 0 ; i < nCount ; ++i ) + { + rtl::OUString aURL = pSeq[i]; + if( xSFA->isFolder( aURL ) ) + { + implCollectXhpFiles( aURL, o_rXhpFileVector, xSFA ); + } + else + { + sal_Int32 nLastDot = aURL.lastIndexOf( '.' ); + if( nLastDot != -1 ) + { + rtl::OUString aExt = aURL.copy( nLastDot + 1 ); + if( aExt.equalsIgnoreAsciiCase( rtl::OUString::createFromAscii( "xhp" ) ) ) + o_rXhpFileVector.push_back( aURL ); + } + } + } +} Databases::~Databases() { @@ -353,48 +449,49 @@ rtl::OUString Databases::getURLMode() } -std::vector< rtl::OUString > Databases::getModuleList( const rtl::OUString& Language ) +const std::vector< rtl::OUString >& Databases::getModuleList( const rtl::OUString& Language ) { - rtl::OUString fileName,dirName = getInstallPathAsURL() + lang( Language ); - osl::Directory dirFile( dirName ); + if( m_avModules.size() == 0 ) + { + rtl::OUString fileName,dirName = getInstallPathAsURL() + lang( Language ); + osl::Directory dirFile( dirName ); - osl::DirectoryItem aDirItem; - osl::FileStatus aStatus( FileStatusMask_FileName ); + osl::DirectoryItem aDirItem; + osl::FileStatus aStatus( FileStatusMask_FileName ); - std::vector< rtl::OUString > ret; - sal_Int32 idx; + sal_Int32 idx; - if( osl::FileBase::E_None != dirFile.open() ) - return ret; + if( osl::FileBase::E_None != dirFile.open() ) + return m_avModules; - while( dirFile.getNextItem( aDirItem ) == osl::FileBase::E_None && - aDirItem.getFileStatus( aStatus ) == osl::FileBase::E_None ) - { - if( ! aStatus.isValid( FileStatusMask_FileName ) ) - continue; + while( dirFile.getNextItem( aDirItem ) == osl::FileBase::E_None && + aDirItem.getFileStatus( aStatus ) == osl::FileBase::E_None ) + { + if( ! aStatus.isValid( FileStatusMask_FileName ) ) + continue; - fileName = aStatus.getFileName(); + fileName = aStatus.getFileName(); - // Check, whether fileName is of the form *.cfg - idx = fileName.lastIndexOf( sal_Unicode( '.' ) ); + // Check, whether fileName is of the form *.cfg + idx = fileName.lastIndexOf( sal_Unicode( '.' ) ); - if( idx == -1 ) - continue; + if( idx == -1 ) + continue; - const sal_Unicode* str = fileName.getStr(); + const sal_Unicode* str = fileName.getStr(); - if( fileName.getLength() == idx + 4 && - ( str[idx + 1] == 'c' || str[idx + 1] == 'C' ) && - ( str[idx + 2] == 'f' || str[idx + 2] == 'F' ) && - ( str[idx + 3] == 'g' || str[idx + 3] == 'G' ) && - ( fileName = fileName.copy(0,idx).toAsciiLowerCase() ).compareToAscii( "picture" ) != 0 ) { - if(! m_bShowBasic && fileName.compareToAscii("sbasic") == 0 ) - continue; - ret.push_back( fileName ); + if( fileName.getLength() == idx + 4 && + ( str[idx + 1] == 'c' || str[idx + 1] == 'C' ) && + ( str[idx + 2] == 'f' || str[idx + 2] == 'F' ) && + ( str[idx + 3] == 'g' || str[idx + 3] == 'G' ) && + ( fileName = fileName.copy(0,idx).toAsciiLowerCase() ).compareToAscii( "picture" ) != 0 ) { + if(! m_bShowBasic && fileName.compareToAscii("sbasic") == 0 ) + continue; + m_avModules.push_back( fileName ); + } } } - - return ret; + return m_avModules; } @@ -499,6 +596,9 @@ rtl::OUString Databases::lang( const rtl::OUString& Language ) { osl::MutexGuard aGuard( m_aMutex ); + if( Language.equals( aEnglishFallbackLang ) ) + return Language; + rtl::OUString ret; LangSetTable::iterator it = m_aLangSet.find( Language ); @@ -514,7 +614,7 @@ rtl::OUString Databases::lang( const rtl::OUString& Language ) } else if( ( ( idx = Language.indexOf( '-' ) ) != -1 || ( idx = Language.indexOf( '_' ) ) != -1 ) && - osl::FileBase::E_None == osl::DirectoryItem::get( getInstallPathAsURL() + Language.copy( 0,idx ), + osl::FileBase::E_None == osl::DirectoryItem::get( getInstallPathAsURL() + Language.copy( 0,idx ), aDirItem ) ) { ret = Language.copy( 0,idx ); @@ -550,21 +650,29 @@ rtl::OUString Databases::variant( const rtl::OUString& System ) } - Db* Databases::getBerkeley( const rtl::OUString& Database, - const rtl::OUString& Language, - bool helpText ) + const rtl::OUString& Language, bool helpText, + const rtl::OUString* pExtensionPath ) { if( ! Database.getLength() || ! Language.getLength() ) return 0; osl::MutexGuard aGuard( m_aMutex ); - rtl::OUString key = - lang(Language) + - rtl::OUString::createFromAscii( "/" ) + + + rtl::OUString aFileExt( rtl::OUString::createFromAscii( helpText ? ".ht" : ".db" ) ); + rtl::OUString aCorrectedLanguage = lang( Language ); // TODO?: Check special handling for Extensions? + rtl::OUString keyBase = + aCorrectedLanguage + + aSlash + Database + - ( helpText ? rtl::OUString::createFromAscii( ".ht" ) : rtl::OUString::createFromAscii( ".db" ) ); + aFileExt; + + rtl::OUString key; + if( pExtensionPath == NULL ) + key = keyBase; + else + key = *pExtensionPath + keyBase; // make unique std::pair< DatabasesTable::iterator,bool > aPair = m_aDatabases.insert( DatabasesTable::value_type( key,0 ) ); @@ -573,12 +681,18 @@ Db* Databases::getBerkeley( const rtl::OUString& Database, if( aPair.second && ! it->second ) { - Db* table = new Db(); - rtl::OUString fileNameOU = - getInstallPathAsSystemPath() + - key; + rtl::OUString fileNameOU; + if( pExtensionPath ) + { + rtl::OUString aExpandedURL = expandURL( *pExtensionPath ); + osl::FileBase::getSystemPathFromFileURL( aExpandedURL, fileNameOU ); + } + else + fileNameOU = getInstallPathAsSystemPath(); + + fileNameOU += keyBase; rtl::OString fileName( fileNameOU.getStr(),fileNameOU.getLength(),osl_getThreadTextEncoding() ); @@ -595,8 +709,6 @@ Db* Databases::getBerkeley( const rtl::OUString& Database, return it->second; } - - Reference< XCollator > Databases::getCollator( const rtl::OUString& Language, const rtl::OUString& System ) @@ -614,8 +726,8 @@ Databases::getCollator( const rtl::OUString& Language, { it->second = Reference< XCollator > ( - m_xSMgr->createInstance( rtl::OUString::createFromAscii( "com.sun.star.i18n.Collator" ) ), - UNO_QUERY ); + m_xSMgr->createInstanceWithContext( rtl::OUString::createFromAscii( "com.sun.star.i18n.Collator" ), + m_xContext ), UNO_QUERY ); rtl::OUString langStr = lang(Language); rtl::OUString countryStr = country(Language); if( !countryStr.getLength() ) @@ -772,8 +884,6 @@ KeywordInfo::KeywordInfo( const std::vector< KeywordElement >& aVec ) } } - - KeywordInfo* Databases::getKeyword( const rtl::OUString& Database, const rtl::OUString& Language ) { @@ -788,60 +898,109 @@ KeywordInfo* Databases::getKeyword( const rtl::OUString& Database, if( aPair.second && ! it->second ) { - rtl::OUString fileNameOU = - getInstallPathAsSystemPath() + - key + - rtl::OUString::createFromAscii( ".key" ); - - rtl::OString fileName( fileNameOU.getStr(), - fileNameOU.getLength(), - osl_getThreadTextEncoding() ); + std::vector<KeywordInfo::KeywordElement> aVector; - Db table; - if( 0 == table.open( 0,fileName.getStr(),0,DB_BTREE,DB_RDONLY,0644 ) ) + KeyDataBaseFileIterator aDbFileIt( m_xContext, *this, Database, Language ); + rtl::OUString fileNameOU; + bool bExtension = false; + while( (fileNameOU = aDbFileIt.nextDbFile( bExtension )).getLength() > 0 ) { - std::vector<KeywordInfo::KeywordElement> aVector; - Db* idmap = getBerkeley( Database,Language ); + rtl::OString fileName( fileNameOU.getStr(), + fileNameOU.getLength(), + osl_getThreadTextEncoding() ); - bool first = true; - - Dbc* cursor = 0; - table.cursor( 0,&cursor,0 ); - Dbt key_,data; - key_.set_flags( DB_DBT_MALLOC ); // Initially the cursor must allocate the necessary memory - data.set_flags( DB_DBT_MALLOC ); - while( cursor && DB_NOTFOUND != cursor->get( &key_,&data,DB_NEXT ) ) + Db table; + if( 0 == table.open( 0,fileName.getStr(),0,DB_BTREE,DB_RDONLY,0644 ) ) { - rtl::OUString keyword( static_cast<sal_Char*>(key_.get_data()), - key_.get_size(), - RTL_TEXTENCODING_UTF8 ); - rtl::OUString doclist( static_cast<sal_Char*>(data.get_data()), - data.get_size(), - RTL_TEXTENCODING_UTF8 ); - - aVector.push_back( KeywordInfo::KeywordElement( this, - idmap, - keyword, - doclist ) ); - if( first ) + Db* idmap = getBerkeley( Database,Language ); + + bool first = true; + + Dbc* cursor = 0; + table.cursor( 0,&cursor,0 ); + Dbt key_,data; + key_.set_flags( DB_DBT_MALLOC ); // Initially the cursor must allocate the necessary memory + data.set_flags( DB_DBT_MALLOC ); + while( cursor && DB_NOTFOUND != cursor->get( &key_,&data,DB_NEXT ) ) { - key_.set_flags( DB_DBT_REALLOC ); - data.set_flags( DB_DBT_REALLOC ); - first = false; - } - } + rtl::OUString keyword( static_cast<sal_Char*>(key_.get_data()), + key_.get_size(), + RTL_TEXTENCODING_UTF8 ); + rtl::OUString doclist( static_cast<sal_Char*>(data.get_data()), + data.get_size(), + RTL_TEXTENCODING_UTF8 ); + + bool bBelongsToDatabase = true; + if( bExtension ) + { + // Analyse doclist string to find module assignments + bool bFoundAtLeastOneModule = false; + bool bModuleMatch = false; + sal_Int32 nLen = doclist.getLength(); + sal_Int32 nLastFound = doclist.lastIndexOf( sal_Unicode(';') ); + if( nLastFound == -1 ) + nLastFound = nLen; + const sal_Unicode* pStr = doclist.getStr(); + sal_Int32 nFound = doclist.lastIndexOf( sal_Unicode('_') ); + while( nFound != -1 ) + { + // Simple optimization, stop if '_' is followed by "id" + if( nLen - nFound > 2 ) + { + if( pStr[ nFound + 1 ] == sal_Unicode('i') && + pStr[ nFound + 2 ] == sal_Unicode('d') ) + break; + } + + rtl::OUString aModule = doclist.copy( nFound + 1, nLastFound - nFound - 1 ); + std::vector< rtl::OUString >::iterator result = std::find( m_avModules.begin(), m_avModules.end(), aModule ); + if( result != m_avModules.end() ) + { + bFoundAtLeastOneModule = true; + if( Database == aModule ) + { + bModuleMatch = true; + break; + } + } + + nLastFound = nFound; + if( nLastFound == 0 ) + break; + nFound = doclist.lastIndexOf( sal_Unicode('_'), nLastFound - 1 ); + } + + if( bFoundAtLeastOneModule && !bModuleMatch ) + bBelongsToDatabase = false; + } - if( cursor ) cursor->close(); + if( !bBelongsToDatabase ) + continue; - // sorting - Reference< XCollator > xCollator = getCollator( Language,rtl::OUString()); - KeywordElementComparator aComparator( xCollator ); - std::sort(aVector.begin(),aVector.end(),aComparator); + aVector.push_back( KeywordInfo::KeywordElement( this, + idmap, + keyword, + doclist ) ); + if( first ) + { + key_.set_flags( DB_DBT_REALLOC ); + data.set_flags( DB_DBT_REALLOC ); + first = false; + } + } - KeywordInfo* pInfo = it->second = new KeywordInfo( aVector ); - (void)pInfo; + if( cursor ) cursor->close(); + } + table.close( 0 ); } - table.close( 0 ); + + // sorting + Reference< XCollator > xCollator = getCollator( Language,rtl::OUString()); + KeywordElementComparator aComparator( xCollator ); + std::sort(aVector.begin(),aVector.end(),aComparator); + + KeywordInfo* pInfo = it->second = new KeywordInfo( aVector ); + (void)pInfo; } return it->second; @@ -855,7 +1014,7 @@ Reference< XHierarchicalNameAccess > Databases::jarFile( const rtl::OUString& ja { return Reference< XHierarchicalNameAccess >( 0 ); } - rtl::OUString key = lang(Language) + rtl::OUString::createFromAscii( "/" ) + jar; + rtl::OUString key = lang(Language) + aSlash + jar; osl::MutexGuard aGuard( m_aMutex ); @@ -867,7 +1026,28 @@ Reference< XHierarchicalNameAccess > Databases::jarFile( const rtl::OUString& ja rtl::OUString zipFile; try { - zipFile = getInstallPathAsURL() + key; + // Extension jar file? Search for ? + sal_Int32 nQuestionMark1 = jar.indexOf( sal_Unicode('?') ); + sal_Int32 nQuestionMark2 = jar.lastIndexOf( sal_Unicode('?') ); + if( nQuestionMark1 != -1 && nQuestionMark2 != -1 && nQuestionMark1 != nQuestionMark2 ) + { + ::rtl::OUString aExtensionPath = jar.copy( nQuestionMark1 + 1, nQuestionMark2 - nQuestionMark1 - 1 ); + ::rtl::OUString aPureJar = jar.copy( nQuestionMark2 + 1 ); + + rtl::OUStringBuffer aStrBuf; + aStrBuf.append( aExtensionPath ); + aStrBuf.append( aSlash ); + aStrBuf.append( lang(Language) ); + aStrBuf.append( aSlash ); + aStrBuf.append( aPureJar ); + + zipFile = expandURL( aStrBuf.makeStringAndClear() ); + } + else + { + zipFile = getInstallPathAsURL() + key; + } + Sequence< Any > aArguments( 1 ); XInputStream_impl* p = new XInputStream_impl( zipFile ); @@ -883,10 +1063,10 @@ Reference< XHierarchicalNameAccess > Databases::jarFile( const rtl::OUString& ja } Reference< XInterface > xIfc - = m_xSMgr->createInstanceWithArguments( + = m_xSMgr->createInstanceWithArgumentsAndContext( rtl::OUString::createFromAscii( "com.sun.star.packages.comp.ZipPackage" ), - aArguments ); + aArguments, m_xContext ); if ( xIfc.is() ) { @@ -909,6 +1089,61 @@ Reference< XHierarchicalNameAccess > Databases::jarFile( const rtl::OUString& ja return it->second; } +Reference< XHierarchicalNameAccess > Databases::findJarFileForPath + ( const rtl::OUString& jar, const rtl::OUString& Language, const rtl::OUString& path ) +{ + Reference< XHierarchicalNameAccess > xNA; + if( ! jar.getLength() || + ! Language.getLength() ) + { + return xNA; + } + + JarFileIterator aJarFileIt( m_xContext, *this, jar, Language ); + Reference< XHierarchicalNameAccess > xTestNA; + Reference< deployment::XPackage > xParentPackageBundle; + while( (xTestNA = aJarFileIt.nextJarFile( xParentPackageBundle )).is() ) + { + if( xTestNA.is() && xTestNA->hasByHierarchicalName( path ) ) + { + bool bSuccess = true; + if( xParentPackageBundle.is() ) + { + rtl::OUString aIdentifierInPath; + sal_Int32 nFindSlash = path.indexOf( '/' ); + if( nFindSlash != -1 ) + aIdentifierInPath = path.copy( 0, nFindSlash ); + + beans::Optional<rtl::OUString> aIdentifierOptional = xParentPackageBundle->getIdentifier(); + if( aIdentifierInPath.getLength() && aIdentifierOptional.IsPresent ) + { + rtl::OUString aUnencodedIdentifier = aIdentifierOptional.Value; + rtl::OUString aIdentifier = rtl::Uri::encode( aUnencodedIdentifier, + rtl_UriCharClassPchar, rtl_UriEncodeIgnoreEscapes, RTL_TEXTENCODING_UTF8 ); + + if( !aIdentifierInPath.equals( aIdentifier ) ) + { + // path does not start with extension identifier -> ignore + bSuccess = false; + } + } + else + { + // No identifier -> ignore + bSuccess = false; + } + } + + if( bSuccess ) + { + xNA = xTestNA; + break; + } + } + } + + return xNA; +} void Databases::popupDocument( URLParameter* urlPar,char **buffer,int *byteCount ) { @@ -1071,21 +1306,32 @@ void Databases::cascadingStylesheet( const rtl::OUString& Language, } - void Databases::setActiveText( const rtl::OUString& Module, const rtl::OUString& Language, const rtl::OUString& Id, char** buffer, int* byteCount ) { - Db* db = getBerkeley( Module,Language,true ); + DataBaseIterator aDbIt( m_xContext, *this, Module, Language, true ); + bool bSuccess = false; - if( db ) + Dbt data; + Db* db; + while( (db = aDbIt.nextDb()) != NULL ) { rtl::OString id( Id.getStr(),Id.getLength(),RTL_TEXTENCODING_UTF8 ); Dbt key( static_cast< void* >( const_cast< sal_Char* >( id.getStr() ) ),id.getLength() ); - Dbt data; - db->get( 0,&key,&data,0 ); + + int err = db->get( 0, &key, &data, 0 ); + if( err == 0 ) + { + bSuccess = true; + break; + } + } + + if( bSuccess ) + { int len = data.get_size(); const sal_Char* ptr = static_cast<sal_Char*>( data.get_data() ); @@ -1134,39 +1380,451 @@ void Databases::setInstallPath( const rtl::OUString& aInstDir ) } -// const ::rtl::OUString& implGetZipFileURL() const -// { -// uno::Reference<beans::XPropertySet > mxPathSettings; -// static ::rtl::OUString aRet; - -// if( !aRet.getLength() && mxPathSettings.is() && mxFileAccess.is() ) -// { -// const ::rtl::OUString aZipFileName( ::rtl::OUString::createFromAscii( IMAGES_ZIPFILENAME ) ); -// uno::Any aAny( mxPathSettings->getPropertyValue( ::rtl::OUString::createFromAscii( "UserConfig" ) ) ); -// INetURLObject aZipURL; - -// if( ( aAny >>= aRet ) && aRet.getLength() ) -// { -// aZipURL = INetURLObject( aRet ); -// aZipURL.Append( aZipFileName ); - -// if( !mxFileAccess->exists( aRet = aZipURL.GetMainURL( INetURLObject::NO_DECODE ) ) ) -// { -// uno::Any aAny( mxPathSettings->getPropertyValue( ::rtl::OUString::createFromAscii( "Config" ) ) ); - -// if( ( aAny >>= aRet ) && aRet.getLength() ) -// { -// aZipURL = INetURLObject( aRet ); -// aZipURL.Append( aZipFileName ); - -// if( !mxFileAccess->exists( aRet = aZipURL.GetMainURL( INetURLObject::NO_DECODE ) ) ) -// { -// aRet = ::rtl::OUString(); -// } -// } -// } -// } -// } - -// return aRet; -// } +//=================================================================== +// class ExtensionIteratorBase + +ExtensionIteratorBase::ExtensionIteratorBase( Reference< XComponentContext > xContext, + Databases& rDatabases, const rtl::OUString& aInitialModule, const rtl::OUString& aLanguage ) + : m_xContext( xContext ) + , m_rDatabases( rDatabases ) + , m_eState( INITIAL_MODULE ) + , m_aInitialModule( aInitialModule ) + , m_aLanguage( aLanguage ) + , m_aCorrectedLanguage( rDatabases.lang( aLanguage ) ) +{ + init(); +} + +ExtensionIteratorBase::ExtensionIteratorBase( Databases& rDatabases, + const rtl::OUString& aInitialModule, const rtl::OUString& aLanguage ) + : m_rDatabases( rDatabases ) + , m_eState( INITIAL_MODULE ) + , m_aInitialModule( aInitialModule ) + , m_aLanguage( aLanguage ) + , m_aCorrectedLanguage( rDatabases.lang( aLanguage ) ) +{ + init(); +} + +ExtensionIteratorBase::ExtensionIteratorBase( Reference< XComponentContext > xContext, Databases& rDatabases ) + : m_xContext( xContext ) + , m_rDatabases( rDatabases ) + , m_eState( USER_EXTENSIONS ) +{ + init(); +} + +void ExtensionIteratorBase::init() +{ + if( !m_xContext.is() ) + { + Reference< XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory(); + Reference< XPropertySet > xProps( xFactory, UNO_QUERY ); + OSL_ASSERT( xProps.is() ); + if (xProps.is()) + { + xProps->getPropertyValue( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ) ) >>= m_xContext; + OSL_ASSERT( m_xContext.is() ); + } + } + if( !m_xContext.is() ) + { + throw RuntimeException( + ::rtl::OUString::createFromAscii( "ExtensionIteratorBase::init(), no XComponentContext" ), + Reference< XInterface >() ); + } + + Reference< XMultiComponentFactory > xSMgr( m_xContext->getServiceManager(), UNO_QUERY ); + m_xSFA = Reference< ucb::XSimpleFileAccess >( + xSMgr->createInstanceWithContext( rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ), + m_xContext ), UNO_QUERY_THROW ); + + m_bUserPackagesLoaded = false; + m_bSharedPackagesLoaded = false; + m_iUserPackage = 0; + m_iSharedPackage = 0; +} + +Reference< deployment::XPackage > ExtensionIteratorBase::implGetHelpPackageFromPackage + ( Reference< deployment::XPackage > xPackage, Reference< deployment::XPackage >& o_xParentPackageBundle ) +{ + o_xParentPackageBundle.clear(); + + Reference< deployment::XPackage > xHelpPackage; + if( !xPackage.is() ) + return xHelpPackage; + + // Check if parent package is registered + beans::Optional< beans::Ambiguous<sal_Bool> > option( xPackage->isRegistered + ( Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>() ) ); + bool bRegistered = false; + if( option.IsPresent ) + { + beans::Ambiguous<sal_Bool> const & reg = option.Value; + if( !reg.IsAmbiguous && reg.Value ) + bRegistered = true; + } + if( !bRegistered ) + return xHelpPackage; + + if( xPackage->isBundle() ) + { + Sequence< Reference< deployment::XPackage > > aPkgSeq = xPackage->getBundle + ( Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>() ); + sal_Int32 nPkgCount = aPkgSeq.getLength(); + const Reference< deployment::XPackage >* pSeq = aPkgSeq.getConstArray(); + for( sal_Int32 iPkg = 0 ; iPkg < nPkgCount ; ++iPkg ) + { + const Reference< deployment::XPackage > xSubPkg = pSeq[ iPkg ]; + const Reference< deployment::XPackageTypeInfo > xPackageTypeInfo = xSubPkg->getPackageType(); + rtl::OUString aMediaType = xPackageTypeInfo->getMediaType(); + if( aMediaType.equals( aHelpMediaType ) ) + { + xHelpPackage = xSubPkg; + o_xParentPackageBundle = xPackage; + break; + } + } + } + else + { + const Reference< deployment::XPackageTypeInfo > xPackageTypeInfo = xPackage->getPackageType(); + rtl::OUString aMediaType = xPackageTypeInfo->getMediaType(); + if( aMediaType.equals( aHelpMediaType ) ) + xHelpPackage = xPackage; + } + + return xHelpPackage; +} + +Reference< deployment::XPackage > ExtensionIteratorBase::implGetNextUserHelpPackage + ( Reference< deployment::XPackage >& o_xParentPackageBundle ) +{ + Reference< deployment::XPackage > xHelpPackage; + + if( !m_bUserPackagesLoaded ) + { + Reference< XPackageManager > xUserManager = + thePackageManagerFactory::get( m_xContext )->getPackageManager( rtl::OUString::createFromAscii("user") ); + m_aUserPackagesSeq = xUserManager->getDeployedPackages + ( Reference< task::XAbortChannel >(), Reference< ucb::XCommandEnvironment >() ); + + m_bUserPackagesLoaded = true; + } + + if( m_iUserPackage == m_aUserPackagesSeq.getLength() ) + { + m_eState = SHARED_EXTENSIONS; // Later: SHARED_MODULE + } + else + { + const Reference< deployment::XPackage >* pUserPackages = m_aUserPackagesSeq.getConstArray(); + Reference< deployment::XPackage > xPackage = pUserPackages[ m_iUserPackage++ ]; + VOS_ENSURE( xPackage.is(), "ExtensionIteratorBase::implGetNextUserHelpPackage(): Invalid package" ); + xHelpPackage = implGetHelpPackageFromPackage( xPackage, o_xParentPackageBundle ); + } + + return xHelpPackage; +} + +Reference< deployment::XPackage > ExtensionIteratorBase::implGetNextSharedHelpPackage + ( Reference< deployment::XPackage >& o_xParentPackageBundle ) +{ + Reference< deployment::XPackage > xHelpPackage; + + if( !m_bSharedPackagesLoaded ) + { + Reference< XPackageManager > xSharedManager = + thePackageManagerFactory::get( m_xContext )->getPackageManager( rtl::OUString::createFromAscii("shared") ); + m_aSharedPackagesSeq = xSharedManager->getDeployedPackages + ( Reference< task::XAbortChannel >(), Reference< ucb::XCommandEnvironment >() ); + + m_bSharedPackagesLoaded = true; + } + + if( m_iSharedPackage == m_aSharedPackagesSeq.getLength() ) + { + m_eState = END_REACHED; + } + else + { + const Reference< deployment::XPackage >* pSharedPackages = m_aSharedPackagesSeq.getConstArray(); + Reference< deployment::XPackage > xPackage = pSharedPackages[ m_iSharedPackage++ ]; + VOS_ENSURE( xPackage.is(), "ExtensionIteratorBase::implGetNextSharedHelpPackage(): Invalid package" ); + xHelpPackage = implGetHelpPackageFromPackage( xPackage, o_xParentPackageBundle ); + } + + return xHelpPackage; +} + + +//=================================================================== +// class DataBaseIterator + +Db* DataBaseIterator::nextDb( rtl::OUString* o_pExtensionPath ) +{ + Db* pRetDb = NULL; + + while( !pRetDb && m_eState != END_REACHED ) + { + switch( m_eState ) + { + case INITIAL_MODULE: + pRetDb = m_rDatabases.getBerkeley( m_aInitialModule, m_aLanguage, m_bHelpText ); + m_eState = USER_EXTENSIONS; // Later: SHARED_MODULE + break; + + // Later: + //case SHARED_MODULE + //... + + case USER_EXTENSIONS: + { + Reference< deployment::XPackage > xParentPackageBundle; + Reference< deployment::XPackage > xHelpPackage = implGetNextUserHelpPackage( xParentPackageBundle ); + if( !xHelpPackage.is() ) + break; + pRetDb = implGetDbFromPackage( xHelpPackage, o_pExtensionPath ); + break; + } + + case SHARED_EXTENSIONS: + { + Reference< deployment::XPackage > xParentPackageBundle; + Reference< deployment::XPackage > xHelpPackage = implGetNextSharedHelpPackage( xParentPackageBundle ); + if( !xHelpPackage.is() ) + break; + + pRetDb = implGetDbFromPackage( xHelpPackage, o_pExtensionPath ); + break; + } + case END_REACHED: + VOS_ENSURE( false, "DataBaseIterator::nextDb(): Invalid case END_REACHED" ); + break; + } + } + + return pRetDb; +} + +Db* DataBaseIterator::implGetDbFromPackage( Reference< deployment::XPackage > xPackage, + rtl::OUString* o_pExtensionPath ) +{ + rtl::OUString aExtensionPath = xPackage->getURL(); + if( o_pExtensionPath ) + *o_pExtensionPath = aExtensionPath; + aExtensionPath += aSlash; + + Db* pRetDb = m_rDatabases.getBerkeley( aHelpFilesBaseName, m_aLanguage, + m_bHelpText, &aExtensionPath ); + + // Fallback to en + if( !pRetDb && !m_aCorrectedLanguage.equals( aEnglishFallbackLang ) ) + pRetDb = m_rDatabases.getBerkeley( aHelpFilesBaseName, aEnglishFallbackLang, m_bHelpText, &aExtensionPath ); + + return pRetDb; +} + + +//=================================================================== +// class KeyDataBaseFileIterator + +rtl::OUString KeyDataBaseFileIterator::nextDbFile( bool& o_rbExtension ) +{ + rtl::OUString aRetFile; + + while( !aRetFile.getLength() && m_eState != END_REACHED ) + { + switch( m_eState ) + { + case INITIAL_MODULE: + aRetFile = + m_rDatabases.getInstallPathAsSystemPath() + + m_aCorrectedLanguage + aSlash + m_aInitialModule + + rtl::OUString::createFromAscii( ".key" ); + + o_rbExtension = false; + + m_eState = USER_EXTENSIONS; // Later: SHARED_MODULE + break; + + // Later: + //case SHARED_MODULE + //... + + case USER_EXTENSIONS: + { + Reference< deployment::XPackage > xParentPackageBundle; + Reference< deployment::XPackage > xHelpPackage = implGetNextUserHelpPackage( xParentPackageBundle ); + if( !xHelpPackage.is() ) + break; + + aRetFile = implGetDbFileFromPackage( xHelpPackage ); + o_rbExtension = true; + break; + } + + case SHARED_EXTENSIONS: + { + Reference< deployment::XPackage > xParentPackageBundle; + Reference< deployment::XPackage > xHelpPackage = implGetNextSharedHelpPackage( xParentPackageBundle ); + if( !xHelpPackage.is() ) + break; + + aRetFile = implGetDbFileFromPackage( xHelpPackage ); + o_rbExtension = true; + break; + } + case END_REACHED: + VOS_ENSURE( false, "DataBaseIterator::nextDbFile(): Invalid case END_REACHED" ); + break; + } + } + + return aRetFile; +} + +rtl::OUString KeyDataBaseFileIterator::implGetDbFileFromPackage + ( Reference< deployment::XPackage > xPackage ) +{ + rtl::OUString aExpandedURL; + rtl::OUString aLanguage = m_aCorrectedLanguage; + for( sal_Int32 iPass = 0 ; iPass < 2 ; ++iPass ) + { + rtl::OUStringBuffer aStrBuf; + aStrBuf.append( xPackage->getURL() ); + aStrBuf.append( aSlash ); + aStrBuf.append( aLanguage ); + aStrBuf.append( aSlash ); + aStrBuf.append( aHelpFilesBaseName ); + aStrBuf.appendAscii( ".key" ); + + aExpandedURL = m_rDatabases.expandURL( aStrBuf.makeStringAndClear() ); + if( iPass == 0 ) + { + if( m_xSFA->exists( aExpandedURL ) ) + break; + if( m_aCorrectedLanguage.equals( aEnglishFallbackLang ) ) + break; + aLanguage = aEnglishFallbackLang; + } + } + rtl::OUString aRetFile; + osl::FileBase::getSystemPathFromFileURL( aExpandedURL, aRetFile ); + + return aRetFile; +} + + +//=================================================================== +// class JarFileIterator + +Reference< XHierarchicalNameAccess > JarFileIterator::nextJarFile + ( Reference< deployment::XPackage >& o_xParentPackageBundle ) +{ + Reference< XHierarchicalNameAccess > xNA; + + while( !xNA.is() && m_eState != END_REACHED ) + { + switch( m_eState ) + { + case INITIAL_MODULE: + xNA = m_rDatabases.jarFile( m_aInitialModule, m_aLanguage ); + m_eState = USER_EXTENSIONS; // Later: SHARED_MODULE + break; + + // Later: + //case SHARED_MODULE + //... + + case USER_EXTENSIONS: + { + Reference< deployment::XPackage > xHelpPackage = implGetNextUserHelpPackage( o_xParentPackageBundle ); + if( !xHelpPackage.is() ) + break; + + xNA = implGetJarFromPackage( xHelpPackage ); + break; + } + + case SHARED_EXTENSIONS: + { + Reference< deployment::XPackage > xHelpPackage = implGetNextSharedHelpPackage( o_xParentPackageBundle ); + if( !xHelpPackage.is() ) + break; + + xNA = implGetJarFromPackage( xHelpPackage ); + break; + } + case END_REACHED: + VOS_ENSURE( false, "JarFileIterator::nextJarFile(): Invalid case END_REACHED" ); + break; + } + } + + return xNA; +} + +Reference< XHierarchicalNameAccess > JarFileIterator::implGetJarFromPackage + ( Reference< deployment::XPackage > xPackage ) +{ + Reference< XHierarchicalNameAccess > xNA; + + rtl::OUString aExtensionPath = xPackage->getURL(); + + rtl::OUString zipFile; + rtl::OUString aLanguage = m_aCorrectedLanguage; + for( sal_Int32 iPass = 0 ; iPass < 2 ; ++iPass ) + { + rtl::OUStringBuffer aStrBuf; + aStrBuf.append( aExtensionPath ); + aStrBuf.append( aSlash ); + aStrBuf.append( aLanguage ); + aStrBuf.append( aSlash ); + aStrBuf.append( aHelpFilesBaseName ); + aStrBuf.append( rtl::OUString::createFromAscii( ".jar" ) ); + + zipFile = m_rDatabases.expandURL( aStrBuf.makeStringAndClear() ); + if( iPass == 0 ) + { + if( m_xSFA->exists( zipFile ) ) + break; + if( m_aCorrectedLanguage.equals( aEnglishFallbackLang ) ) + break; + aLanguage = aEnglishFallbackLang; + } + } + + try + { + Sequence< Any > aArguments( 1 ); + aArguments[ 0 ] <<= zipFile; + + // ??? To be used also in Extension context? + //XInputStream_impl* p = new XInputStream_impl( zipFile ); + + Reference< XMultiComponentFactory >xSMgr( m_xContext->getServiceManager(), UNO_QUERY ); + Reference< XInterface > xIfc + = xSMgr->createInstanceWithArgumentsAndContext( + rtl::OUString::createFromAscii( + "com.sun.star.packages.comp.ZipPackage" ), + aArguments, m_xContext ); + + if ( xIfc.is() ) + { + xNA = Reference< XHierarchicalNameAccess >( xIfc, UNO_QUERY ); + + VOS_ENSURE( xNA.is(), + "JarFileIterator::implGetJarFromPackage() - " + "Got no hierarchical name access!" ); + } + } + catch ( RuntimeException & ) + {} + catch ( Exception & ) + {} + + return xNA; +} + |