diff options
author | Jens-Heiner Rechtien <hr@openoffice.org> | 2009-05-15 12:21:35 +0000 |
---|---|---|
committer | Jens-Heiner Rechtien <hr@openoffice.org> | 2009-05-15 12:21:35 +0000 |
commit | 7950f402d62f33a531d78909adcfb6e9e69c3048 (patch) | |
tree | 9331baa1d7e128f63a9f45ff697f9c2ab08110cd | |
parent | 922445f4f200e0292cea9c76769ad979fa87bbb1 (diff) |
CWS-TOOLING: integrate CWS ab68
2009-03-26 11:37:32 +0100 ab r270063 : #i98680# Handle missing lucene
2009-03-16 12:23:38 +0100 ab r269520 : #i100228# Introduced own file format instead of using berkeley db
2009-02-27 11:48:05 +0100 ab r268572 : #i86003# Redesigned language fallback behavior
-rw-r--r-- | desktop/source/deployment/registry/help/dp_help.cxx | 40 | ||||
-rw-r--r-- | xmlhelp/source/com/sun/star/help/HelpIndexer.java | 60 | ||||
-rw-r--r-- | xmlhelp/source/com/sun/star/help/HelpLinker.cxx | 109 | ||||
-rw-r--r-- | xmlhelp/source/cxxhelp/provider/databases.cxx | 588 | ||||
-rw-r--r-- | xmlhelp/source/cxxhelp/provider/databases.hxx | 26 | ||||
-rw-r--r-- | xmlhelp/source/cxxhelp/provider/db.cxx | 449 | ||||
-rw-r--r-- | xmlhelp/source/cxxhelp/provider/db.hxx | 97 | ||||
-rw-r--r-- | xmlhelp/source/cxxhelp/provider/resultsetforquery.cxx | 7 | ||||
-rw-r--r-- | xmlhelp/source/cxxhelp/provider/urlparameter.cxx | 41 | ||||
-rw-r--r-- | xmlhelp/source/treeview/tvread.cxx | 58 | ||||
-rw-r--r-- | xmlhelp/source/treeview/tvread.hxx | 3 |
11 files changed, 1226 insertions, 252 deletions
diff --git a/desktop/source/deployment/registry/help/dp_help.cxx b/desktop/source/deployment/registry/help/dp_help.cxx index bfd7bff3cb54..573c1c639de1 100644 --- a/desktop/source/deployment/registry/help/dp_help.cxx +++ b/desktop/source/deployment/registry/help/dp_help.cxx @@ -94,6 +94,7 @@ class BackendImpl : public ::dp_registry::backend::PackageRegistryBackend void implProcessHelp( Reference< deployment::XPackage > xPackage, bool doRegisterPackage ); void implCollectXhpFiles( const rtl::OUString& aDir, std::vector< rtl::OUString >& o_rXhpFileVector ); + rtl::OUString getFlagFileURL( Reference< deployment::XPackage > xPackage, const char* pFlagStr ); rtl::OUString getRegisteredFlagFileURL( Reference< deployment::XPackage > xPackage ); rtl::OUString getCompiledFlagFileURL( Reference< deployment::XPackage > xPackage ); rtl::OUString expandURL( const rtl::OUString& aURL ); @@ -264,9 +265,16 @@ void BackendImpl::implProcessHelp Reference< script::XInvocation > xInvocation; if( xContext.is() ) { - xInvocation = Reference< script::XInvocation >( - xContext->getServiceManager()->createInstanceWithContext( rtl::OUString::createFromAscii( - "com.sun.star.help.HelpIndexer" ), xContext ) , UNO_QUERY ); + try + { + xInvocation = Reference< script::XInvocation >( + xContext->getServiceManager()->createInstanceWithContext( rtl::OUString::createFromAscii( + "com.sun.star.help.HelpIndexer" ), xContext ) , UNO_QUERY ); + } + catch (Exception &) + { + // i98680: Survive missing lucene + } } // Scan languages @@ -351,8 +359,13 @@ void BackendImpl::implProcessHelp Sequence<uno::Any> aParamsSeq( 6 ); aParamsSeq[0] = uno::makeAny( rtl::OUString::createFromAscii( "-lang" ) ); - rtl::OUString aLang; // TODO - aLang = rtl::OUString::createFromAscii( "de" ); // TODO + + rtl::OUString aLang; + sal_Int32 nLastSlash = aLangURL.lastIndexOf( '/' ); + if( nLastSlash != -1 ) + aLang = aLangURL.copy( nLastSlash + 1 ); + else + aLang = rtl::OUString::createFromAscii( "en" ); aParamsSeq[1] = uno::makeAny( aLang ); aParamsSeq[2] = uno::makeAny( rtl::OUString::createFromAscii( "-mod" ) ); @@ -441,26 +454,25 @@ void BackendImpl::implProcessHelp } } -rtl::OUString BackendImpl::getRegisteredFlagFileURL( Reference< deployment::XPackage > xPackage ) +rtl::OUString BackendImpl::getFlagFileURL( Reference< deployment::XPackage > xPackage, const char* pFlagStr ) { rtl::OUString aRetURL; if( !xPackage.is() ) return aRetURL; rtl::OUString aHelpURL = xPackage->getURL(); aRetURL = expandURL( aHelpURL ); - aRetURL += rtl::OUString::createFromAscii( "/RegisteredFlag" ); + aRetURL += rtl::OUString::createFromAscii( pFlagStr ); return aRetURL; } +rtl::OUString BackendImpl::getRegisteredFlagFileURL( Reference< deployment::XPackage > xPackage ) +{ + return getFlagFileURL( xPackage, "/RegisteredFlag" ); +} + rtl::OUString BackendImpl::getCompiledFlagFileURL( Reference< deployment::XPackage > xPackage ) { - rtl::OUString aRetURL; - if( !xPackage.is() ) - return aRetURL; - rtl::OUString aHelpURL = xPackage->getURL(); - aRetURL = expandURL( aHelpURL ); - aRetURL += rtl::OUString::createFromAscii( "/CompiledFlag" ); - return aRetURL; + return getFlagFileURL( xPackage, "/CompiledFlag" ); } rtl::OUString BackendImpl::expandURL( const rtl::OUString& aURL ) diff --git a/xmlhelp/source/com/sun/star/help/HelpIndexer.java b/xmlhelp/source/com/sun/star/help/HelpIndexer.java index 9b5da8253d70..eabf1fdd6e88 100644 --- a/xmlhelp/source/com/sun/star/help/HelpIndexer.java +++ b/xmlhelp/source/com/sun/star/help/HelpIndexer.java @@ -82,6 +82,7 @@ public class HelpIndexer extends WeakBase private static void mainImpl( String[] args, boolean bExtensionMode ) { String aDirToZipStr = ""; + String aSrcDirStr = ""; String aLanguageStr = ""; String aModule = ""; String aTargetZipFileStr = ""; @@ -90,6 +91,7 @@ public class HelpIndexer extends WeakBase boolean bLang = false; boolean bMod = false; boolean bZipDir = false; + boolean bSrcDir = false; boolean bOutput = false; int nArgCount = args.length; @@ -122,6 +124,15 @@ public class HelpIndexer extends WeakBase } i++; } + else if( "-srcdir".equals(args[i]) ) + { + if( i + 1 < nArgCount ) + { + aSrcDirStr = args[i + 1]; + bSrcDir = true; + } + i++; + } else if( "-o".equals(args[i]) ) { if( i + 1 < nArgCount ) @@ -142,45 +153,55 @@ public class HelpIndexer extends WeakBase System.exit( -1 ); } - File docDir = new File( aDirToZipStr ); String aIndexDirName = aModule + ".idxl"; File aIndexDir = new File( aDirToZipStr + File.separator + aIndexDirName ); - File aCaptionFilesDir = new File( aDirToZipStr + File.separator + "caption" ); - File aContentFilesDir = new File( aDirToZipStr + File.separator + "content" ); + if( !bSrcDir ) + aSrcDirStr = aDirToZipStr; + File aCaptionFilesDir = new File( aSrcDirStr + File.separator + "caption" ); + File aContentFilesDir = new File( aSrcDirStr + File.separator + "content" ); try { Date start = new Date(); Analyzer analyzer = aLanguageStr.equals("ja") ? (Analyzer)new CJKAnalyzer() : (Analyzer)new StandardAnalyzer(); IndexWriter writer = new IndexWriter( aIndexDir, analyzer, true ); - System.out.println( "Lucene: Indexing to directory '" + aIndexDir + "'..." ); - int nRet = indexDocs( writer, aModule, aCaptionFilesDir, aContentFilesDir ); + if( !bExtensionMode ) + System.out.println( "Lucene: Indexing to directory '" + aIndexDir + "'..." ); + int nRet = indexDocs( writer, aModule, bExtensionMode, aCaptionFilesDir, aContentFilesDir ); if( nRet != -1 ) { - System.out.println(); - System.out.println( "Optimizing ..." ); + if( !bExtensionMode ) + { + System.out.println(); + System.out.println( "Optimizing ..." ); + } writer.optimize(); } writer.close(); if( bExtensionMode ) { - deleteRecursively( aCaptionFilesDir ); - deleteRecursively( aContentFilesDir ); + if( !bSrcDir ) + { + deleteRecursively( aCaptionFilesDir ); + deleteRecursively( aContentFilesDir ); + } } else { if( nRet == -1 ) deleteRecursively( aIndexDir ); - System.out.println( "Zipping ..." ); + if( !bExtensionMode ) + System.out.println( "Zipping ..." ); File aDirToZipFile = new File( aDirToZipStr ); createZipFile( aDirToZipFile, aTargetZipFileStr ); deleteRecursively( aDirToZipFile ); } Date end = new Date(); - System.out.println(end.getTime() - start.getTime() + " total milliseconds"); + if( !bExtensionMode ) + System.out.println(end.getTime() - start.getTime() + " total milliseconds"); } catch (IOException e) { @@ -193,17 +214,19 @@ public class HelpIndexer extends WeakBase } } - private static int indexDocs(IndexWriter writer, String aModule, + private static int indexDocs(IndexWriter writer, String aModule, boolean bExtensionMode, File aCaptionFilesDir, File aContentFilesDir) throws IOException { if( !aCaptionFilesDir.canRead() || !aCaptionFilesDir.isDirectory() ) { - System.out.println( "Not found: " + aCaptionFilesDir ); + if( !bExtensionMode ) + System.out.println( "Not found: " + aCaptionFilesDir ); return -1; } if( !aContentFilesDir.canRead() || !aContentFilesDir.isDirectory() ) { - System.out.println( "Not found: " + aContentFilesDir ); + if( !bExtensionMode ) + System.out.println( "Not found: " + aContentFilesDir ); return -1; } @@ -216,7 +239,8 @@ public class HelpIndexer extends WeakBase HashSet aContentFilesHashSet = new HashSet( aContentFilesList ); // Loop over caption files and find corresponding content file - System.out.println( "Indexing, adding files" ); + if( !bExtensionMode ) + System.out.println( "Indexing, adding files" ); int nCaptionFilesLen = aCaptionFiles.length; for( int i = 0 ; i < nCaptionFilesLen ; i++ ) { @@ -226,7 +250,8 @@ public class HelpIndexer extends WeakBase if( aContentFilesHashSet.contains( aCaptionFileStr ) ) aContentFile = new File( aContentFilesDir, aCaptionFileStr ); - System.out.print( "." ); + if( !bExtensionMode ) + System.out.print( "." ); writer.addDocument( HelpFileDocument.Document( aModule, aCaptionFile, aContentFile ) ); } @@ -240,7 +265,8 @@ public class HelpIndexer extends WeakBase // Not already handled in caption files loop File aCaptionFile = null; File aContentFile = new File( aContentFilesDir, aContentFileStr ); - System.out.print( "." ); + if( !bExtensionMode ) + System.out.print( "." ); writer.addDocument( HelpFileDocument.Document( aModule, aCaptionFile, aContentFile ) ); } } diff --git a/xmlhelp/source/com/sun/star/help/HelpLinker.cxx b/xmlhelp/source/com/sun/star/help/HelpLinker.cxx index a696f32977b8..67049df439e1 100644 --- a/xmlhelp/source/com/sun/star/help/HelpLinker.cxx +++ b/xmlhelp/source/com/sun/star/help/HelpLinker.cxx @@ -51,6 +51,9 @@ #include <expat/xmlparse.h> #endif +#define DBHELP_ONLY + + class IndexerPreProcessor { private: @@ -166,6 +169,22 @@ struct Data } }; +void writeKeyValue_DBHelp( FILE* pFile, const std::string& aKeyStr, const std::string& aValueStr ) +{ + if( pFile == NULL ) + return; + char cLF = 10; + int nKeyLen = aKeyStr.length(); + int nValueLen = aValueStr.length(); + fprintf( pFile, "%x ", nKeyLen ); + if( nKeyLen > 0 ) + fwrite( aKeyStr.c_str(), 1, nKeyLen, pFile );
+ fprintf( pFile, " %x ", nValueLen ); + if( nValueLen > 0 ) + fwrite( aValueStr.c_str(), 1, nValueLen, pFile );
+ fprintf( pFile, "%c", cLF ); +} + class HelpKeyword { private: @@ -200,6 +219,19 @@ public: table->put(table, NULL, &key, &value, 0); } } + + void dump_DBHelp( const std::string& rFileName ) + { + FILE* pFile = fopen( rFileName.c_str(), "wb" ); + if( pFile == NULL ) + return; + + DataHashtable::const_iterator aEnd = _hash.end(); + for (DataHashtable::const_iterator aIter = _hash.begin(); aIter != aEnd; ++aIter) + writeKeyValue_DBHelp( pFile, aIter->first, aIter->second.getString() ); + + fclose( pFile ); + } }; class HelpLinker @@ -237,7 +269,7 @@ private: IndexerPreProcessor* m_pIndexerPreProcessor; void initIndexerPreProcessor(); void link() throw( HelpProcessingException ); - void addBookmark( DB* dbBase, std::string thishid, + void addBookmark( DB* dbBase, FILE* pFile_DBHelp, std::string thishid, const std::string& fileB, const std::string& anchorB, const std::string& jarfileB, const std::string& titleB ); #if 0 @@ -277,7 +309,7 @@ namespace URLEncoder } } -void HelpLinker::addBookmark( DB* dbBase, std::string thishid, +void HelpLinker::addBookmark( DB* dbBase, FILE* pFile_DBHelp, std::string thishid, const std::string& fileB, const std::string& anchorB, const std::string& jarfileB, const std::string& titleB) { @@ -327,7 +359,14 @@ void HelpLinker::addBookmark( DB* dbBase, std::string thishid, data.data = &dataB[0]; data.size = dataB.size(); - dbBase->put(dbBase, NULL, &key, &data, 0); + if( dbBase != NULL ) + dbBase->put(dbBase, NULL, &key, &data, 0); + + if( pFile_DBHelp != NULL ) + { + std::string aValueStr( dataB.begin(), dataB.end() ); + writeKeyValue_DBHelp( pFile_DBHelp, thishid, aValueStr ); + } } void HelpLinker::initIndexerPreProcessor() @@ -346,7 +385,7 @@ void HelpLinker::initIndexerPreProcessor() void HelpLinker::link() throw( HelpProcessingException ) { bool bIndexForExtension = true;
- +
if( bExtensionMode ) { indexDirParentName = sourceRoot; @@ -371,23 +410,45 @@ void HelpLinker::link() throw( HelpProcessingException ) if (appl[0] == 's') appl = appl.substr(1); - fs::path helpTextFileName(indexDirParentName / (mod + ".ht")); + bool bUse_ = true; +#ifdef DBHELP_ONLY + if( !bExtensionMode ) + bUse_ = false; +#endif + DB* helpText(0); +#ifndef DBHELP_ONLY + fs::path helpTextFileName(indexDirParentName / (mod + ".ht")); db_create(&helpText,0,0); helpText->open(helpText, NULL, helpTextFileName.native_file_string().c_str(), NULL, DB_BTREE, DB_CREATE | DB_TRUNCATE, 0644); +#endif + + fs::path helpTextFileName_DBHelp(indexDirParentName / (mod + (bUse_ ? ".ht_" : ".ht"))); + FILE* pFileHelpText_DBHelp = fopen + ( helpTextFileName_DBHelp.native_file_string().c_str(), "wb" ); - fs::path dbBaseFileName(indexDirParentName / (mod + ".db")); DB* dbBase(0); +#ifndef DBHELP_ONLY + fs::path dbBaseFileName(indexDirParentName / (mod + ".db")); db_create(&dbBase,0,0); dbBase->open(dbBase, NULL, dbBaseFileName.native_file_string().c_str(), NULL, DB_BTREE, DB_CREATE | DB_TRUNCATE, 0644); +#endif - fs::path keyWordFileName(indexDirParentName / (mod + ".key")); + fs::path dbBaseFileName_DBHelp(indexDirParentName / (mod + (bUse_ ? ".db_" : ".db"))); + FILE* pFileDbBase_DBHelp = fopen + ( dbBaseFileName_DBHelp.native_file_string().c_str(), "wb" ); + +#ifndef DBHELP_ONLY DB* keyWord(0); + fs::path keyWordFileName(indexDirParentName / (mod + ".key")); db_create(&keyWord,0,0); keyWord->open(keyWord, NULL, keyWordFileName.native_file_string().c_str(), NULL, DB_BTREE, DB_CREATE | DB_TRUNCATE, 0644); +#endif + + fs::path keyWordFileName_DBHelp(indexDirParentName / (mod + (bUse_ ? ".key_" : ".key"))); HelpKeyword helpKeyword; @@ -423,8 +484,11 @@ void HelpLinker::link() throw( HelpProcessingException ) HashSet::iterator end = helpFiles.end(); for (HashSet::iterator iter = helpFiles.begin(); iter != end; ++iter) { - std::cout << "."; - std::cout.flush(); + if( !bExtensionMode ) + { + std::cout << "."; + std::cout.flush(); + } // process one file // streamTable contains the streams in the hzip file @@ -500,7 +564,7 @@ void HelpLinker::link() throw( HelpProcessingException ) std::string& titleB = documentTitle; // add once this as its own id. - addBookmark(dbBase, documentPath, fileB, std::string(), jarfileB, titleB); + addBookmark(dbBase, pFileDbBase_DBHelp, documentPath, fileB, std::string(), jarfileB, titleB); // first the database *.db // ByteArrayInputStream bais = null; @@ -525,7 +589,7 @@ void HelpLinker::link() throw( HelpProcessingException ) anchorB = thishid.substr(1 + index); thishid = thishid.substr(0, index); } - addBookmark(dbBase, thishid, fileB, anchorB, jarfileB, titleB); + addBookmark(dbBase, pFileDbBase_DBHelp, thishid, fileB, anchorB, jarfileB, titleB); } } @@ -541,7 +605,7 @@ void HelpLinker::link() throw( HelpProcessingException ) enumer != aEnd; ++enumer) { const std::string &anchor = enumer->first; - addBookmark(dbBase, documentPath, fileB, + addBookmark(dbBase, pFileDbBase_DBHelp, documentPath, fileB, anchor, jarfileB, titleB); std::string totalId = fakedHid + "#" + anchor; // std::cerr << hzipFileName << std::endl; @@ -587,7 +651,12 @@ void HelpLinker::link() throw( HelpProcessingException ) memset(&textDbt, 0, sizeof(textDbt)); textDbt.data = const_cast<char*>(helpTextText.c_str()); textDbt.size = helpTextText.length(); - helpText->put(helpText, NULL, &keyDbt, &textDbt, 0); + + if( helpText != NULL ) + helpText->put(helpText, NULL, &keyDbt, &textDbt, 0); + + if( pFileHelpText_DBHelp != NULL ) + writeKeyValue_DBHelp( pFileHelpText_DBHelp, helpTextId, helpTextText ); } } @@ -614,16 +683,30 @@ void HelpLinker::link() throw( HelpProcessingException ) catch( HelpProcessingException& ) { // catch HelpProcessingException to avoid locking data bases +#ifndef DBHELP_ONLY helpText->close(helpText, 0); dbBase->close(dbBase, 0); keyWord->close(keyWord, 0); +#endif + if( pFileHelpText_DBHelp != NULL ) + fclose( pFileHelpText_DBHelp ); + if( pFileDbBase_DBHelp != NULL ) + fclose( pFileDbBase_DBHelp ); throw; } +#ifndef DBHELP_ONLY helpText->close(helpText, 0); dbBase->close(dbBase, 0); helpKeyword.dump(keyWord); keyWord->close(keyWord, 0); +#endif + if( pFileHelpText_DBHelp != NULL ) + fclose( pFileHelpText_DBHelp ); + if( pFileDbBase_DBHelp != NULL ) + fclose( pFileDbBase_DBHelp ); + + helpKeyword.dump_DBHelp( keyWordFileName_DBHelp.native_file_string() ); if( !bExtensionMode ) { diff --git a/xmlhelp/source/cxxhelp/provider/databases.cxx b/xmlhelp/source/cxxhelp/provider/databases.cxx index c96378e15ed7..8130e5f38bd2 100644 --- a/xmlhelp/source/cxxhelp/provider/databases.cxx +++ b/xmlhelp/source/cxxhelp/provider/databases.cxx @@ -56,6 +56,8 @@ #include <com/sun/star/util/XMacroExpander.hpp> #include <com/sun/star/uri/XUriReferenceFactory.hpp> #include <com/sun/star/uri/XVndSunStarExpandUrl.hpp> +#include <com/sun/star/script/XInvocation.hpp> +#include <comphelper/locale.hxx> #include <xmlhelp/compilehelp.hxx> @@ -76,7 +78,6 @@ 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 ) @@ -180,34 +181,10 @@ Databases::Databases( sal_Bool showBasic, m_vReplacement[6] = productVersion; 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 ); - } - } - } + m_xSFA = Reference< ucb::XSimpleFileAccess >( + m_xSMgr->createInstanceWithContext( rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ), + m_xContext ), UNO_QUERY_THROW ); } Databases::~Databases() @@ -425,7 +402,7 @@ const std::vector< rtl::OUString >& Databases::getModuleList( const rtl::OUStrin { if( m_avModules.size() == 0 ) { - rtl::OUString fileName,dirName = getInstallPathAsURL() + lang( Language ); + rtl::OUString fileName,dirName = getInstallPathAsURL() + processLang( Language ); osl::Directory dirFile( dirName ); osl::DirectoryItem aDirItem; @@ -473,7 +450,7 @@ StaticModuleInformation* Databases::getStaticInformationForModule( const rtl::OU { osl::MutexGuard aGuard( m_aMutex ); - rtl::OUString key = lang(Language) + rtl::OUString::createFromAscii( "/" ) + Module; + rtl::OUString key = processLang(Language) + rtl::OUString::createFromAscii( "/" ) + Module; std::pair< ModInfoTable::iterator,bool > aPair = m_aModInfo.insert( ModInfoTable::value_type( key,0 ) ); @@ -564,13 +541,10 @@ StaticModuleInformation* Databases::getStaticInformationForModule( const rtl::OU -rtl::OUString Databases::lang( const rtl::OUString& Language ) +rtl::OUString Databases::processLang( 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 ); @@ -612,16 +586,6 @@ rtl::OUString Databases::country( const rtl::OUString& Language ) -rtl::OUString Databases::variant( const rtl::OUString& System ) -{ - if( System.compareToAscii( "WIN" ) == 0 || - System.compareToAscii( "MAC" ) ) - return System; - else - return rtl::OUString::createFromAscii( "POSIX" ); -} - - Db* Databases::getBerkeley( const rtl::OUString& Database, const rtl::OUString& Language, bool helpText, const rtl::OUString* pExtensionPath ) @@ -633,18 +597,12 @@ Db* Databases::getBerkeley( const rtl::OUString& Database, 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 + - aFileExt; - + rtl::OUString dbFileName = aSlash + Database + aFileExt; rtl::OUString key; if( pExtensionPath == NULL ) - key = keyBase; + key = processLang( Language ) + dbFileName; else - key = *pExtensionPath + keyBase; // make unique + key = *pExtensionPath + Language + dbFileName; // make unique, don't change language std::pair< DatabasesTable::iterator,bool > aPair = m_aDatabases.insert( DatabasesTable::value_type( key,0 ) ); @@ -659,16 +617,33 @@ Db* Databases::getBerkeley( const rtl::OUString& Database, if( pExtensionPath ) { rtl::OUString aExpandedURL = expandURL( *pExtensionPath ); + aExpandedURL += Language + dbFileName; osl::FileBase::getSystemPathFromFileURL( aExpandedURL, fileNameOU ); } else - fileNameOU = getInstallPathAsSystemPath(); + fileNameOU = getInstallPathAsSystemPath() + key; - fileNameOU += keyBase; rtl::OString fileName( fileNameOU.getStr(),fileNameOU.getLength(),osl_getThreadTextEncoding() ); - if( table->open( 0,fileName.getStr(),0,DB_BTREE,DB_RDONLY,0644 ) ) + rtl::OUString fileNameDBHelp( fileNameOU ); + if( pExtensionPath != NULL ) + fileNameDBHelp += rtl::OUString::createFromAscii( "_" ); + if( m_xSFA->exists( fileNameDBHelp ) ) + { + DBHelp* pDBHelp = new DBHelp( fileNameDBHelp, m_xSFA ); + table->setDBHelp( pDBHelp ); + +#ifdef TEST_DBHELP + bool bSuccess; + bool bOldDbAccess = false; + bSuccess = pDBHelp->testAgainstDb( fileName, bOldDbAccess ); + + bOldDbAccess = true; + bSuccess = pDBHelp->testAgainstDb( fileName, bOldDbAccess ); +#endif + } + else if( table->open( 0,fileName.getStr(),0,DB_BTREE,DB_RDONLY,0644 ) ) { table->close( 0 ); delete table; @@ -700,7 +675,7 @@ Databases::getCollator( const rtl::OUString& Language, Reference< XCollator > ( m_xSMgr->createInstanceWithContext( rtl::OUString::createFromAscii( "com.sun.star.i18n.Collator" ), m_xContext ), UNO_QUERY ); - rtl::OUString langStr = lang(Language); + rtl::OUString langStr = processLang(Language); rtl::OUString countryStr = country(Language); if( !countryStr.getLength() ) { @@ -818,20 +793,44 @@ void KeywordInfo::KeywordElement::init( Databases *pDatabases,Db* pDb,const rtl: listId.realloc( id.size() ); listAnchor.realloc( id.size() ); listTitle.realloc( id.size() ); + + int nSize = 0; + const sal_Char* pData = NULL; + const sal_Char pEmpty[] = ""; + for( sal_uInt32 i = 0; i < id.size(); ++i ) { listId[i] = id[i]; listAnchor[i] = anchor[i]; - rtl::OString idi( id[i].getStr(),id[i].getLength(),RTL_TEXTENCODING_UTF8 ); - Dbt key_( static_cast< void* >( const_cast< sal_Char* >( idi.getStr() ) ), - idi.getLength() ); - Dbt data; + nSize = 0; + pData = pEmpty; if( pDb ) - pDb->get( 0,&key_,&data,0 ); + { + rtl::OString idi( id[i].getStr(),id[i].getLength(),RTL_TEXTENCODING_UTF8 ); + DBHelp* pDBHelp = pDb->getDBHelp(); + if( pDBHelp != NULL ) + { + DBData aDBData; + bool bSuccess = pDBHelp->getValueForKey( idi, aDBData ); + if( bSuccess ) + { + nSize = aDBData.getSize(); + pData = aDBData.getData(); + } + } + else + { + Dbt key_( static_cast< void* >( const_cast< sal_Char* >( idi.getStr() ) ), + idi.getLength() ); + Dbt data; + pDb->get( 0,&key_,&data,0 ); + nSize = data.get_size(); + pData = static_cast<sal_Char*>( data.get_data() ); + } + } - DbtToStringConverter converter( static_cast< sal_Char* >( data.get_data() ), - data.get_size() ); + DbtToStringConverter converter( pData, nSize ); rtl::OUString title = converter.getTitle(); pDatabases->replaceName( title ); @@ -856,12 +855,61 @@ KeywordInfo::KeywordInfo( const std::vector< KeywordElement >& aVec ) } } +bool Databases::checkModuleMatchForExtension + ( const rtl::OUString& Database, const rtl::OUString& doclist ) +{ + bool bBelongsToDatabase = true; + + // 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; + + return bBelongsToDatabase; +} + + KeywordInfo* Databases::getKeyword( const rtl::OUString& Database, const rtl::OUString& Language ) { osl::MutexGuard aGuard( m_aMutex ); - rtl::OUString key = lang(Language) + rtl::OUString::createFromAscii( "/" ) + Database; + rtl::OUString key = processLang(Language) + rtl::OUString::createFromAscii( "/" ) + Database; std::pair< KeywordInfoTable::iterator,bool > aPair = m_aKeywordInfo.insert( KeywordInfoTable::value_type( key,0 ) ); @@ -882,7 +930,66 @@ KeywordInfo* Databases::getKeyword( const rtl::OUString& Database, osl_getThreadTextEncoding() ); Db table; - if( 0 == table.open( 0,fileName.getStr(),0,DB_BTREE,DB_RDONLY,0644 ) ) + + rtl::OUString fileNameDBHelp( fileNameOU ); + if( bExtension ) + fileNameDBHelp += rtl::OUString::createFromAscii( "_" ); + if( m_xSFA->exists( fileNameDBHelp ) ) + { + DBHelp aDBHelp( fileNameDBHelp, m_xSFA ); + + DBData aKey; + DBData aValue; + if( aDBHelp.startIteration() ) + { + Db* idmap = getBerkeley( Database,Language ); + + DBHelp* pDBHelp = idmap->getDBHelp(); + if( pDBHelp != NULL ) + { + bool bOptimizeForPerformance = true; + pDBHelp->releaseHashMap(); + pDBHelp->createHashMap( bOptimizeForPerformance ); + } + + while( aDBHelp.getNextKeyAndValue( aKey, aValue ) ) + { + rtl::OUString keyword( aKey.getData(), aKey.getSize(), + RTL_TEXTENCODING_UTF8 ); + rtl::OUString doclist( aValue.getData(), aValue.getSize(), + RTL_TEXTENCODING_UTF8 ); + + bool bBelongsToDatabase = true; + if( bExtension ) + bBelongsToDatabase = checkModuleMatchForExtension( Database, doclist ); + + if( !bBelongsToDatabase ) + continue; + + aVector.push_back( KeywordInfo::KeywordElement( this, + idmap, + keyword, + doclist ) ); + } + aDBHelp.stopIteration(); + + if( pDBHelp != NULL ) + pDBHelp->releaseHashMap(); + } + +#ifdef TEST_DBHELP + bool bSuccess; + bool bOldDbAccess = false; + bSuccess = aDBHelp.testAgainstDb( fileName, bOldDbAccess ); + + bOldDbAccess = true; + bSuccess = aDBHelp.testAgainstDb( fileName, bOldDbAccess ); + + int nDummy = 0; +#endif + } + + else if( 0 == table.open( 0,fileName.getStr(),0,DB_BTREE,DB_RDONLY,0644 ) ) { Db* idmap = getBerkeley( Database,Language ); @@ -904,47 +1011,7 @@ KeywordInfo* Databases::getKeyword( const rtl::OUString& Database, 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; - } + bBelongsToDatabase = checkModuleMatchForExtension( Database, doclist ); if( !bBelongsToDatabase ) continue; @@ -986,7 +1053,7 @@ Reference< XHierarchicalNameAccess > Databases::jarFile( const rtl::OUString& ja { return Reference< XHierarchicalNameAccess >( 0 ); } - rtl::OUString key = lang(Language) + aSlash + jar; + rtl::OUString key = processLang(Language) + aSlash + jar; osl::MutexGuard aGuard( m_aMutex ); @@ -1009,8 +1076,6 @@ Reference< XHierarchicalNameAccess > Databases::jarFile( const rtl::OUString& ja rtl::OUStringBuffer aStrBuf; aStrBuf.append( aExtensionPath ); aStrBuf.append( aSlash ); - aStrBuf.append( lang(Language) ); - aStrBuf.append( aSlash ); aStrBuf.append( aPureJar ); zipFile = expandURL( aStrBuf.makeStringAndClear() ); @@ -1183,7 +1248,7 @@ void Databases::cascadingStylesheet( const rtl::OUString& Language, if( retry == 2 ) fileURL = getInstallPathAsURL() + - lang( Language ) + + processLang( Language ) + rtl::OUString::createFromAscii( "/" ) + m_aCSS + rtl::OUString::createFromAscii( ".css" ); @@ -1235,53 +1300,66 @@ void Databases::setActiveText( const rtl::OUString& Module, int* byteCount ) { DataBaseIterator aDbIt( m_xContext, *this, Module, Language, true ); - bool bSuccess = false; // #i84550 Cache information about failed ids rtl::OString id( Id.getStr(),Id.getLength(),RTL_TEXTENCODING_UTF8 ); EmptyActiveTextSet::iterator it = m_aEmptyActiveTextSet.find( id ); bool bFoundAsEmpty = ( it != m_aEmptyActiveTextSet.end() ); Dbt data; + DBData aDBData; + + int nSize = 0; + const sal_Char* pData = NULL; + + bool bSuccess = false; if( !bFoundAsEmpty ) { Db* db; Dbt key( static_cast< void* >( const_cast< sal_Char* >( id.getStr() ) ),id.getLength() ); - while( (db = aDbIt.nextDb()) != NULL ) + while( !bSuccess && (db = aDbIt.nextDb()) != NULL ) { - int err = db->get( 0, &key, &data, 0 ); - if( err == 0 ) + DBHelp* pDBHelp = db->getDBHelp(); + if( pDBHelp != NULL ) { - bSuccess = true; - break; + bSuccess = pDBHelp->getValueForKey( id, aDBData ); + nSize = aDBData.getSize(); + pData = aDBData.getData(); + } + else + { + int err = db->get( 0, &key, &data, 0 ); + if( err == 0 ) + { + bSuccess = true; + nSize = data.get_size(); + pData = static_cast<sal_Char*>( data.get_data() ); + } } } } if( bSuccess ) { - int len = data.get_size(); - const sal_Char* ptr = static_cast<sal_Char*>( data.get_data() ); - // ensure existence of tmp after for rtl::OString tmp; - for( int i = 0; i < len; ++i ) - if( ptr[i] == '%' || ptr[i] == '$' ) + for( int i = 0; i < nSize; ++i ) + if( pData[i] == '%' || pData[i] == '$' ) { // need of replacement - rtl::OUString temp = rtl::OUString( ptr,len,RTL_TEXTENCODING_UTF8 ); + rtl::OUString temp = rtl::OUString( pData, nSize, RTL_TEXTENCODING_UTF8 ); replaceName( temp ); tmp = rtl::OString( temp.getStr(), temp.getLength(), RTL_TEXTENCODING_UTF8 ); - len = tmp.getLength(); - ptr = tmp.getStr(); + nSize = tmp.getLength(); + pData = tmp.getStr(); break; } - *byteCount = len; - *buffer = new char[ 1 + len ]; - (*buffer)[len] = 0; - rtl_copyMemory( *buffer,ptr,len ); + *byteCount = nSize; + *buffer = new char[ 1 + nSize ]; + (*buffer)[nSize] = 0; + rtl_copyMemory( *buffer, pData, nSize ); } else { @@ -1321,7 +1399,6 @@ ExtensionIteratorBase::ExtensionIteratorBase( Reference< XComponentContext > xCo , m_eState( INITIAL_MODULE ) , m_aInitialModule( aInitialModule ) , m_aLanguage( aLanguage ) - , m_aCorrectedLanguage( rDatabases.lang( aLanguage ) ) { init(); } @@ -1332,7 +1409,6 @@ ExtensionIteratorBase::ExtensionIteratorBase( Databases& rDatabases, , m_eState( INITIAL_MODULE ) , m_aInitialModule( aInitialModule ) , m_aLanguage( aLanguage ) - , m_aCorrectedLanguage( rDatabases.lang( aLanguage ) ) { init(); } @@ -1492,34 +1568,87 @@ Reference< deployment::XPackage > ExtensionIteratorBase::implGetNextSharedHelpPa return xHelpPackage; } -rtl::OUString ExtensionIteratorBase::implGetFileFromPackage( const rtl::OUString& rFileExtension, - com::sun::star::uno::Reference< com::sun::star::deployment::XPackage > xPackage ) +rtl::OUString ExtensionIteratorBase::implGetFileFromPackage( + const rtl::OUString& rFileExtension, Reference< deployment::XPackage > xPackage ) { + // No extension -> search for pure language folder + bool bLangFolderOnly = (rFileExtension.getLength() == 0); + rtl::OUString aFile; - rtl::OUString aLanguage = m_aCorrectedLanguage; + rtl::OUString aLanguage = m_aLanguage; 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.append( rFileExtension ); + if( !bLangFolderOnly ) + { + aStrBuf.append( aSlash ); + aStrBuf.append( aHelpFilesBaseName ); + aStrBuf.append( rFileExtension ); + } aFile = m_rDatabases.expandURL( aStrBuf.makeStringAndClear() ); if( iPass == 0 ) { if( m_xSFA->exists( aFile ) ) break; - if( m_aCorrectedLanguage.equals( aEnglishFallbackLang ) ) - break; - aLanguage = aEnglishFallbackLang; + + ::std::vector< ::rtl::OUString > av; + implGetLanguageVectorFromPackage( av, xPackage ); + ::std::vector< ::rtl::OUString >::const_iterator pFound = av.end(); + try
+ {
+ pFound = ::comphelper::Locale::getFallback( av, m_aLanguage );
+ }
+ catch( ::comphelper::Locale::MalFormedLocaleException& ) + {} + if( pFound != av.end() )
+ aLanguage = *pFound;
} } return aFile; } +inline bool isLetter( sal_Unicode c ) +{ + bool bLetter = ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')); + return bLetter; +} + +void ExtensionIteratorBase::implGetLanguageVectorFromPackage( ::std::vector< ::rtl::OUString > &rv, + com::sun::star::uno::Reference< com::sun::star::deployment::XPackage > xPackage ) +{ + rv.clear(); + rtl::OUString aExtensionPath = xPackage->getURL(); + Sequence< rtl::OUString > aEntrySeq = m_xSFA->getFolderContents( aExtensionPath, true );
+ + const rtl::OUString* pSeq = aEntrySeq.getConstArray(); + sal_Int32 nCount = aEntrySeq.getLength(); + for( sal_Int32 i = 0 ; i < nCount ; ++i ) + { + rtl::OUString aEntry = pSeq[i]; + if( m_xSFA->isFolder( aEntry ) ) + { + sal_Int32 nLastSlash = aEntry.lastIndexOf( '/' ); + if( nLastSlash != -1 ) + { + rtl::OUString aPureEntry = aEntry.copy( nLastSlash + 1 ); + + // Check language sceme + int nLen = aPureEntry.getLength(); + const sal_Unicode* pc = aPureEntry.getStr(); + bool bStartCanBeLanguage = ( nLen >= 2 && isLetter( pc[0] ) && isLetter( pc[1] ) ); + bool bIsLanguage = bStartCanBeLanguage && + ( nLen == 2 || (nLen == 5 && pc[2] == '-' && isLetter( pc[3] ) && isLetter( pc[4] )) ); + if( bIsLanguage ) + rv.push_back( aPureEntry ); + } + } + }
+} + //=================================================================== // class DataBaseIterator @@ -1574,16 +1703,35 @@ Db* DataBaseIterator::implGetDbFromPackage( Reference< deployment::XPackage > xP rtl::OUString* o_pExtensionPath ) { rtl::OUString aExtensionPath = xPackage->getURL(); - if( o_pExtensionPath ) - *o_pExtensionPath = aExtensionPath; + //if( o_pExtensionPath ) + //*o_pExtensionPath = aExtensionPath; aExtensionPath += aSlash; - Db* pRetDb = m_rDatabases.getBerkeley( aHelpFilesBaseName, m_aLanguage, + rtl::OUString aUsedLanguage = m_aLanguage; + Db* pRetDb = m_rDatabases.getBerkeley( aHelpFilesBaseName, aUsedLanguage, m_bHelpText, &aExtensionPath ); - // Fallback to en - if( !pRetDb && !m_aCorrectedLanguage.equals( aEnglishFallbackLang ) ) - pRetDb = m_rDatabases.getBerkeley( aHelpFilesBaseName, aEnglishFallbackLang, m_bHelpText, &aExtensionPath ); + // Language fallback + if( !pRetDb ) + { + ::std::vector< ::rtl::OUString > av; + implGetLanguageVectorFromPackage( av, xPackage ); + ::std::vector< ::rtl::OUString >::const_iterator pFound = av.end(); + try
+ {
+ pFound = ::comphelper::Locale::getFallback( av, m_aLanguage );
+ }
+ catch( ::comphelper::Locale::MalFormedLocaleException& ) + {} + if( pFound != av.end() )
+ { + aUsedLanguage = *pFound;
+ pRetDb = m_rDatabases.getBerkeley( aHelpFilesBaseName, aUsedLanguage, m_bHelpText, &aExtensionPath ); + } + } + + if( o_pExtensionPath ) + *o_pExtensionPath = aExtensionPath + aUsedLanguage; return pRetDb; } @@ -1603,7 +1751,7 @@ rtl::OUString KeyDataBaseFileIterator::nextDbFile( bool& o_rbExtension ) case INITIAL_MODULE: aRetFile = m_rDatabases.getInstallPathAsSystemPath() + - m_aCorrectedLanguage + aSlash + m_aInitialModule + + m_rDatabases.processLang( m_aLanguage ) + aSlash + m_aInitialModule + rtl::OUString::createFromAscii( ".key" ); o_rbExtension = false; @@ -1687,9 +1835,7 @@ Reference< XHierarchicalNameAccess > JarFileIterator::nextJarFile if( !xHelpPackage.is() ) break; - xNA = implGetJarFromPackage( xHelpPackage ); - if( xNA.is() && o_pExtensionPath != NULL ) - *o_pExtensionPath = xHelpPackage->getURL(); + xNA = implGetJarFromPackage( xHelpPackage, o_pExtensionPath ); break; } @@ -1699,9 +1845,7 @@ Reference< XHierarchicalNameAccess > JarFileIterator::nextJarFile if( !xHelpPackage.is() ) break; - xNA = implGetJarFromPackage( xHelpPackage ); - if( xNA.is() && o_pExtensionPath != NULL ) - *o_pExtensionPath = xHelpPackage->getURL(); + xNA = implGetJarFromPackage( xHelpPackage, o_pExtensionPath ); break; } case END_REACHED: @@ -1714,7 +1858,7 @@ Reference< XHierarchicalNameAccess > JarFileIterator::nextJarFile } Reference< XHierarchicalNameAccess > JarFileIterator::implGetJarFromPackage - ( Reference< deployment::XPackage > xPackage ) + ( Reference< deployment::XPackage > xPackage, rtl::OUString* o_pExtensionPath ) { Reference< XHierarchicalNameAccess > xNA; @@ -1726,9 +1870,6 @@ Reference< XHierarchicalNameAccess > JarFileIterator::implGetJarFromPackage 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( @@ -1750,6 +1891,14 @@ Reference< XHierarchicalNameAccess > JarFileIterator::implGetJarFromPackage catch ( Exception & ) {} + if( xNA.is() && o_pExtensionPath != NULL ) + { + // Extract path including language from file name + sal_Int32 nLastSlash = zipFile.lastIndexOf( '/' ); + if( nLastSlash != -1 ) + *o_pExtensionPath = zipFile.copy( 0, nLastSlash ); + } + return xNA; } @@ -1757,7 +1906,7 @@ Reference< XHierarchicalNameAccess > JarFileIterator::implGetJarFromPackage //=================================================================== // class IndexFolderIterator -rtl::OUString IndexFolderIterator::nextIndexFolder( bool& o_rbExtension ) +rtl::OUString IndexFolderIterator::nextIndexFolder( bool& o_rbExtension, bool& o_rbTemporary ) { rtl::OUString aIndexFolder; @@ -1768,9 +1917,10 @@ rtl::OUString IndexFolderIterator::nextIndexFolder( bool& o_rbExtension ) case INITIAL_MODULE: aIndexFolder = m_rDatabases.getInstallPathAsURL() + - m_aCorrectedLanguage + aSlash + m_aInitialModule + + m_rDatabases.processLang( m_aLanguage ) + aSlash + m_aInitialModule + rtl::OUString::createFromAscii( ".idxl" ); + o_rbTemporary = false; o_rbExtension = false; m_eState = USER_EXTENSIONS; // Later: SHARED_MODULE @@ -1787,7 +1937,7 @@ rtl::OUString IndexFolderIterator::nextIndexFolder( bool& o_rbExtension ) if( !xHelpPackage.is() ) break; - aIndexFolder = implGetIndexFolderFromPackage( xHelpPackage ); + aIndexFolder = implGetIndexFolderFromPackage( o_rbTemporary, xHelpPackage ); o_rbExtension = true; break; } @@ -1799,7 +1949,7 @@ rtl::OUString IndexFolderIterator::nextIndexFolder( bool& o_rbExtension ) if( !xHelpPackage.is() ) break; - aIndexFolder = implGetIndexFolderFromPackage( xHelpPackage ); + aIndexFolder = implGetIndexFolderFromPackage( o_rbTemporary, xHelpPackage ); o_rbExtension = true; break; } @@ -1812,10 +1962,124 @@ rtl::OUString IndexFolderIterator::nextIndexFolder( bool& o_rbExtension ) return aIndexFolder; } -rtl::OUString IndexFolderIterator::implGetIndexFolderFromPackage( Reference< deployment::XPackage > xPackage ) +rtl::OUString IndexFolderIterator::implGetIndexFolderFromPackage( bool& o_rbTemporary, Reference< deployment::XPackage > xPackage ) { rtl::OUString aIndexFolder = implGetFileFromPackage( rtl::OUString::createFromAscii( ".idxl" ), xPackage ); + + o_rbTemporary = false; + if( !m_xSFA->isFolder( aIndexFolder ) ) + { + // i98680: Missing index? Try to generate now + rtl::OUString aLangURL = implGetFileFromPackage( rtl::OUString(), xPackage ); + if( m_xSFA->isFolder( aLangURL ) ) + { + // Test write access (shared extension may be read only) + bool bIsWriteAccess = false; + try + { + rtl::OUString aCreateTestFolder = aLangURL + rtl::OUString::createFromAscii( "CreateTestFolder" ); + m_xSFA->createFolder( aCreateTestFolder ); + if( m_xSFA->isFolder( aCreateTestFolder ) ) + bIsWriteAccess = true; + + m_xSFA->kill( aCreateTestFolder ); + } + catch (Exception &) + {} + + // TEST + //bIsWriteAccess = false; + + Reference< script::XInvocation > xInvocation; + Reference< XMultiComponentFactory >xSMgr( m_xContext->getServiceManager(), UNO_QUERY ); + try + { + xInvocation = Reference< script::XInvocation >( + m_xContext->getServiceManager()->createInstanceWithContext( rtl::OUString::createFromAscii( + "com.sun.star.help.HelpIndexer" ), m_xContext ) , UNO_QUERY ); + + if( xInvocation.is() ) + { + Sequence<uno::Any> aParamsSeq( bIsWriteAccess ? 6 : 8 ); + + aParamsSeq[0] = uno::makeAny( rtl::OUString::createFromAscii( "-lang" ) ); + + rtl::OUString aLang; + sal_Int32 nLastSlash = aLangURL.lastIndexOf( '/' ); + if( nLastSlash != -1 ) + aLang = aLangURL.copy( nLastSlash + 1 ); + else + aLang = rtl::OUString::createFromAscii( "en" ); + aParamsSeq[1] = uno::makeAny( aLang ); + + aParamsSeq[2] = uno::makeAny( rtl::OUString::createFromAscii( "-mod" ) ); + aParamsSeq[3] = uno::makeAny( rtl::OUString::createFromAscii( "help" ) ); + + rtl::OUString aZipDir = aLangURL; + if( !bIsWriteAccess ) + { + rtl::OUString aTempFileURL; + ::osl::FileBase::RC eErr = ::osl::File::createTempFile( 0, 0, &aTempFileURL ); + if( eErr == ::osl::FileBase::E_None ) + { + rtl::OUString aTempDirURL = aTempFileURL; + try + { + m_xSFA->kill( aTempDirURL ); + } + catch (Exception &) + {} + m_xSFA->createFolder( aTempDirURL ); + + aZipDir = aTempDirURL; + o_rbTemporary = true; + } + } + + aParamsSeq[4] = uno::makeAny( rtl::OUString::createFromAscii( "-zipdir" ) ); + rtl::OUString aSystemPath; + osl::FileBase::getSystemPathFromFileURL( aZipDir, aSystemPath ); + aParamsSeq[5] = uno::makeAny( aSystemPath ); + + if( !bIsWriteAccess ) + { + aParamsSeq[6] = uno::makeAny( rtl::OUString::createFromAscii( "-srcdir" ) ); + rtl::OUString aSrcDirVal; + osl::FileBase::getSystemPathFromFileURL( aLangURL, aSrcDirVal ); + aParamsSeq[7] = uno::makeAny( aSrcDirVal ); + } + + Sequence< sal_Int16 > aOutParamIndex; + Sequence< uno::Any > aOutParam; + uno::Any aRet = xInvocation->invoke( rtl::OUString::createFromAscii( "createIndex" ), + aParamsSeq, aOutParamIndex, aOutParam ); + + if( bIsWriteAccess ) + aIndexFolder = implGetFileFromPackage( rtl::OUString::createFromAscii( ".idxl" ), xPackage ); + else + aIndexFolder = aZipDir + rtl::OUString::createFromAscii( "/help.idxl" ); + } + } + catch (Exception &) + {} + } + } + return aIndexFolder; } +void IndexFolderIterator::deleteTempIndexFolder( const rtl::OUString& aIndexFolder ) +{ + sal_Int32 nLastSlash = aIndexFolder.lastIndexOf( '/' ); + if( nLastSlash != -1 ) + { + rtl::OUString aTmpFolder = aIndexFolder.copy( 0, nLastSlash ); + try + { + m_xSFA->kill( aTmpFolder ); + } + catch (Exception &) + {} + } +} diff --git a/xmlhelp/source/cxxhelp/provider/databases.hxx b/xmlhelp/source/cxxhelp/provider/databases.hxx index 7839b080c1c6..87491c1b1e45 100644 --- a/xmlhelp/source/cxxhelp/provider/databases.hxx +++ b/xmlhelp/source/cxxhelp/provider/databases.hxx @@ -211,6 +211,7 @@ namespace chelp { StaticModuleInformation* getStaticInformationForModule( const rtl::OUString& Module, const rtl::OUString& Language ); + bool checkModuleMatchForExtension( const rtl::OUString& Database, const rtl::OUString& doclist ); KeywordInfo* getKeyword( const rtl::OUString& Module, const rtl::OUString& Language ); @@ -278,7 +279,7 @@ namespace chelp { * Maps a given language-locale combination to language. */ - rtl::OUString lang( const rtl::OUString& Language ); + rtl::OUString processLang( const rtl::OUString& Language ); /** @@ -289,13 +290,6 @@ namespace chelp { rtl::OUString country( const rtl::OUString& Language ); - /** - * Maps a given System to the variant part of a locale. - */ - - rtl::OUString variant( const rtl::OUString& System ); - - void replaceName( rtl::OUString& oustring ) const; rtl::OUString getProductName() const { return m_vReplacement[0]; } @@ -314,6 +308,7 @@ namespace chelp { osl::Mutex m_aMutex; com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > m_xContext; com::sun::star::uno::Reference< com::sun::star::lang::XMultiComponentFactory > m_xSMgr; + com::sun::star::uno::Reference< com::sun::star::ucb::XSimpleFileAccess > m_xSFA; sal_Bool m_bShowBasic; int m_nErrorDocLength; @@ -402,10 +397,6 @@ namespace chelp { void setInstallPath( const rtl::OUString& aInstallDirectory ); - static void implCollectXhpFiles( const rtl::OUString& aDir, - std::vector< rtl::OUString >& o_rXhpFileVector, - com::sun::star::uno::Reference< com::sun::star::ucb::XSimpleFileAccess > xSFA ); - }; // end class Databases @@ -453,6 +444,8 @@ namespace chelp { ( com::sun::star::uno::Reference< com::sun::star::deployment::XPackage >& o_xParentPackageBundle ); rtl::OUString implGetFileFromPackage( const rtl::OUString& rFileExtension, com::sun::star::uno::Reference< com::sun::star::deployment::XPackage > xPackage ); + void implGetLanguageVectorFromPackage( ::std::vector< ::rtl::OUString > &rv, + com::sun::star::uno::Reference< com::sun::star::deployment::XPackage > xPackage ); com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > m_xContext; com::sun::star::uno::Reference< com::sun::star::ucb::XSimpleFileAccess > m_xSFA; @@ -463,7 +456,6 @@ namespace chelp { rtl::OUString m_aInitialModule; rtl::OUString m_aLanguage; - rtl::OUString m_aCorrectedLanguage; com::sun::star::uno::Sequence< com::sun::star::uno::Reference < com::sun::star::deployment::XPackage > > m_aUserPackagesSeq; @@ -538,7 +530,8 @@ namespace chelp { private: com::sun::star::uno::Reference< com::sun::star::container::XHierarchicalNameAccess > - implGetJarFromPackage(com::sun::star::uno::Reference< com::sun::star::deployment::XPackage > xPackage ); + implGetJarFromPackage(com::sun::star::uno::Reference< com::sun::star::deployment::XPackage > xPackage, + rtl::OUString* o_pExtensionPath = NULL ); }; // end class JarFileIterator @@ -550,10 +543,11 @@ namespace chelp { : ExtensionIteratorBase( rDatabases, aInitialModule, aLanguage ) {} - rtl::OUString nextIndexFolder( bool& o_rbExtension ); + rtl::OUString nextIndexFolder( bool& o_rbExtension, bool& o_rbTemporary ); + void deleteTempIndexFolder( const rtl::OUString& aIndexFolder ); private: - rtl::OUString implGetIndexFolderFromPackage( + rtl::OUString implGetIndexFolderFromPackage( bool& o_rbTemporary, com::sun::star::uno::Reference< com::sun::star::deployment::XPackage > xPackage ); }; // end class KeyDataBaseFileIterator diff --git a/xmlhelp/source/cxxhelp/provider/db.cxx b/xmlhelp/source/cxxhelp/provider/db.cxx index ca3f63c367dd..3cc9b6168076 100644 --- a/xmlhelp/source/cxxhelp/provider/db.cxx +++ b/xmlhelp/source/cxxhelp/provider/db.cxx @@ -36,25 +36,459 @@ #include <rtl/alloc.h> #include <cstring> +#include "com/sun/star/io/XSeekable.hpp" + +#ifdef TEST_DBHELP +#include <osl/time.h>
+#endif
+ +using namespace com::sun::star; +using namespace com::sun::star::uno; +using namespace com::sun::star::io; + namespace berkeleydbproxy { //---------------------------------------------------------------------------- - namespace db_internal +namespace db_internal +{ + // static void raise_error(int dberr, const char * where); + + static inline int check_error(int dberr, const char * where) + { + (void)where; + + // if (dberr) raise_error(dberr,where); + return dberr; + } +} + +void DBData::copyToBuffer( const char* pSrcData, int nSize ) +{ + m_nSize = nSize; + delete m_pBuffer; + m_pBuffer = new char[m_nSize+1]; + memcpy( m_pBuffer, pSrcData, m_nSize ); + m_pBuffer[m_nSize] = 0; +} + + +// DBHelp + +bool DBHelp::implReadLenAndData( const char* pData, int& riPos, DBData& rValue ) +{ + bool bSuccess = false; + + // Read key len + const char* pStartPtr = pData + riPos; + char* pEndPtr; + sal_Int32 nKeyLen = strtol( pStartPtr, &pEndPtr, 16 ); + if( pEndPtr == pStartPtr ) + return bSuccess; + riPos += (pEndPtr - pStartPtr) + 1; + + const char* pKeySrc = pData + riPos; + rValue.copyToBuffer( pKeySrc, nKeyLen ); + riPos += nKeyLen + 1; + + bSuccess = true; + return bSuccess; +} + +#ifdef TEST_DBHELP + +typedef std::pair< rtl::OString, rtl::OString > KeyValPair; +typedef std::vector< KeyValPair > KeyValPairVector; + +void testWriteKeyValue( FILE* pFile, const KeyValPair& rKeyValPair ) +{ + if( pFile == NULL ) + return; + char cLF = 10; + + const rtl::OString& aKeyStr = rKeyValPair.first; + const rtl::OString& aValueStr = rKeyValPair.second; + int nKeyLen = aKeyStr.getLength(); + int nValueLen = aValueStr.getLength(); + fprintf( pFile, "%x ", nKeyLen ); + if( nKeyLen > 0 ) + fwrite( aKeyStr.getStr(), 1, nKeyLen, pFile );
+ fprintf( pFile, " %x ", nValueLen ); + if( nValueLen > 0 ) + fwrite( aValueStr.getStr(), 1, nValueLen, pFile );
+ fprintf( pFile, "%c", cLF ); +} + +bool DBHelp::testAgainstDb( const rtl::OString& fileName, bool bOldDbAccess ) +{ + bool bSuccess = true; + + KeyValPairVector avKeyValPair; + + rtl::OString aOutFileName = fileName; + aOutFileName += "_TestOut"; + if( bOldDbAccess ) + aOutFileName += "_Old"; + FILE* pFile = fopen( aOutFileName.getStr(), "wb" ); + + // Get all values + Db table; + if( 0 == table.open( 0,fileName.getStr(),0,DB_BTREE,DB_RDONLY,0644 ) ) + { + 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 ) ) + { + rtl::OString keyword( static_cast<sal_Char*>(key_.get_data()), + key_.get_size() ); + rtl::OString value( static_cast<sal_Char*>(data.get_data()), + data.get_size() ); + + KeyValPair aPair( keyword, value ); + avKeyValPair.push_back( aPair ); + if( pFile != NULL ) + testWriteKeyValue( pFile, aPair ); + + if( first ) + { + key_.set_flags( DB_DBT_REALLOC ); + data.set_flags( DB_DBT_REALLOC ); + first = false; + } + } + + if( cursor ) cursor->close(); + } + table.close( 0 ); + + // TEST + DBData aDBData; + Db tableTest; + Dbt data; + + int nOkCount = 0; + int nErrCount = 0; + + bool bTestSuccess; + const char* pTestReadData = NULL; + int nTestReadDataSize = 0; + + sal_uInt32 starttime = osl_getGlobalTimer();
+ sal_uInt32 afterfirsttime = starttime;
+
+ if( pFile != NULL ) { - // static void raise_error(int dberr, const char * where); + if( bOldDbAccess ) + fprintf( pFile, "\nTesting old access:\n" ); + else + fprintf( pFile, "\nTesting new access:\n" ); + } + + KeyValPairVector::const_iterator it; + bool bFirst = true; + for( it = avKeyValPair.begin() ; it != avKeyValPair.end() ; ++it ) + { + const KeyValPair& rKeyValPair = *it; + + const rtl::OString& aKeyStr = rKeyValPair.first; + const rtl::OString& aValueStr = rKeyValPair.second; + int nKeyLen = aKeyStr.getLength(); + int nValueLen = aValueStr.getLength(); - static inline int check_error(int dberr, const char * where) + const sal_Char* ptr = aValueStr.getStr(); + + bTestSuccess = false; + pTestReadData = NULL; + nTestReadDataSize = 0; + if( bOldDbAccess ) + { + if( bFirst ) + { + if( tableTest.open( 0,fileName.getStr(),0,DB_BTREE,DB_RDONLY,0644 ) ) + { + if( pFile != NULL ) + fprintf( pFile, "Cannot open database\n" ); + + break; + } + } + + Dbt key( static_cast< void* >( const_cast< sal_Char* >( aKeyStr.getStr() ) ), aKeyStr.getLength() ); + int err = tableTest.get( 0, &key, &data, 0 ); + if( err == 0 ) + { + bTestSuccess = true; + pTestReadData = static_cast< sal_Char* >( data.get_data() ); + nTestReadDataSize = data.get_size(); + } + } + else + { + bTestSuccess = getValueForKey( aKeyStr, aDBData ); + if( bTestSuccess ) + { + pTestReadData = aDBData.getData(); + nTestReadDataSize = aDBData.getSize(); + } + } + if( bFirst ) + { + afterfirsttime = osl_getGlobalTimer();
+ bFirst = false; + } + int nError = 0; + if( bTestSuccess && pTestReadData != NULL ) { - (void)where; + int nCmp = memcmp( ptr, pTestReadData, nValueLen );
+ if( nCmp == 0 )
+ ++nOkCount;
+ else
+ nError = 1;
+
+ if( nValueLen != nTestReadDataSize ) + nError = 2;
+ } + else + nError = 3; - // if (dberr) raise_error(dberr,where); - return dberr; + if( nError != 0 ) + { + bSuccess = false; + ++nErrCount; + + if( pFile != NULL ) + { + fprintf( pFile, "ERROR, not found:\n" ); + testWriteKeyValue( pFile, rKeyValPair ); + fprintf( pFile, "\nError Code: %d\n", nError ); + }
} } + tableTest.close( 0 ); + + sal_uInt32 endtime = osl_getGlobalTimer();
+ double dDiffTime = (endtime-starttime) / 1000.0;
+ double dDiffFirstTime = (afterfirsttime-starttime) / 1000.0;
+ if( pFile != NULL ) + { + int nCount = avKeyValPair.size(); + fprintf( pFile, "%d key/values in total, read %d correctly, %d errors\n", + nCount, nOkCount, nErrCount ); + fprintf( pFile, "Time taken: %g s (First access %g s)\n", dDiffTime, dDiffFirstTime ); + fprintf( pFile, "Average time per access: %g s\n", dDiffTime / nCount ); + } + + if( pFile != NULL ) + fclose( pFile ); + + return bSuccess; +} + +#endif + + +void DBHelp::createHashMap( bool bOptimizeForPerformance ) +{ + releaseHashMap(); + if( bOptimizeForPerformance ) + { + if( m_pStringToDataMap != NULL ) + return; + m_pStringToDataMap = new StringToDataMap(); + } + else + { + if( m_pStringToValPosMap != NULL ) + return; + m_pStringToValPosMap = new StringToValPosMap(); + } + + Reference< XInputStream > xIn = m_xSFA->openFileRead( m_aFileName ); + if( xIn.is() ) + { + Sequence< sal_Int8 > aData; + sal_Int32 nSize = m_xSFA->getSize( m_aFileName ); + sal_Int32 nRead = xIn->readBytes( aData, nSize ); + + const char* pData = (const char*)aData.getConstArray(); + int iPos = 0; + while( iPos < nRead ) + { + DBData aDBKey; + if( !implReadLenAndData( pData, iPos, aDBKey ) ) + break; + + rtl::OString aOKeyStr = aDBKey.getData(); + + // Read val len + const char* pStartPtr = pData + iPos; + char* pEndPtr; + sal_Int32 nValLen = strtol( pStartPtr, &pEndPtr, 16 ); + if( pEndPtr == pStartPtr ) + break; + + iPos += (pEndPtr - pStartPtr) + 1; + + if( bOptimizeForPerformance ) + { + const char* pValSrc = pData + iPos; + rtl::OString aValStr( pValSrc, nValLen ); + (*m_pStringToDataMap)[aOKeyStr] = aValStr; + } + else + { + // store value start position + (*m_pStringToValPosMap)[aOKeyStr] = std::pair<int,int>( iPos, nValLen ); + } + iPos += nValLen + 1; + } + + xIn->closeInput(); + } +} + +void DBHelp::releaseHashMap( void ) +{ + if( m_pStringToDataMap != NULL ) + { + delete m_pStringToDataMap; + m_pStringToDataMap = NULL; + } + if( m_pStringToValPosMap != NULL ) + { + delete m_pStringToValPosMap; + m_pStringToValPosMap = NULL; + } +} + + +bool DBHelp::getValueForKey( const rtl::OString& rKey, DBData& rValue ) +{ + bool bSuccess = false; + if( !m_xSFA.is() ) + return bSuccess; + + try + { + + if( m_pStringToDataMap == NULL && m_pStringToValPosMap == NULL ) + { + bool bOptimizeForPerformance = false; + createHashMap( bOptimizeForPerformance ); + } + + if( m_pStringToValPosMap != NULL ) + { + StringToValPosMap::const_iterator it = m_pStringToValPosMap->find( rKey ); + if( it != m_pStringToValPosMap->end() ) + { + const std::pair<int,int>& rValPair = it->second; + int iValuePos = rValPair.first; + int nValueLen = rValPair.second; + + Reference< XInputStream > xIn = m_xSFA->openFileRead( m_aFileName ); + if( xIn.is() ) + { + Reference< XSeekable > xXSeekable( xIn, UNO_QUERY ); + if( xXSeekable.is() ) + { + xXSeekable->seek( iValuePos );
+
+ Sequence< sal_Int8 > aData; + sal_Int32 nRead = xIn->readBytes( aData, nValueLen ); + if( nRead == nValueLen ) + { + const char* pData = (const sal_Char*)aData.getConstArray(); + rValue.copyToBuffer( pData, nValueLen ); + bSuccess = true; + } + } + xIn->closeInput(); + } + } + } + + else if( m_pStringToDataMap != NULL ) + { + StringToDataMap::const_iterator it = m_pStringToDataMap->find( rKey ); + if( it != m_pStringToDataMap->end() ) + { + const rtl::OString& rValueStr = it->second; + int nValueLen = rValueStr.getLength(); + const char* pData = rValueStr.getStr(); + rValue.copyToBuffer( pData, nValueLen ); + bSuccess = true; + } + } + + } + catch( Exception & ) + { + bSuccess = false; + } + + return bSuccess; +} + +bool DBHelp::startIteration( void ) +{ + bool bSuccess = false; + + sal_Int32 nSize = m_xSFA->getSize( m_aFileName ); + + Reference< XInputStream > xIn = m_xSFA->openFileRead( m_aFileName ); + if( xIn.is() ) + { + m_nItRead = xIn->readBytes( m_aItData, nSize ); + if( m_nItRead == nSize ) + { + bSuccess = true; + m_pItData = (const char*)m_aItData.getConstArray(); + m_iItPos = 0; + } + else + { + stopIteration(); + } + } + + return bSuccess; +} + +bool DBHelp::getNextKeyAndValue( DBData& rKey, DBData& rValue ) +{ + bool bSuccess = false; + + if( m_iItPos < m_nItRead ) + { + if( implReadLenAndData( m_pItData, m_iItPos, rKey ) ) + { + if( implReadLenAndData( m_pItData, m_iItPos, rValue ) ) + bSuccess = true; + } + } + + return bSuccess; +} + +void DBHelp::stopIteration( void ) +{ + m_aItData = Sequence<sal_Int8>(); + m_pItData = NULL; + m_nItRead = -1; + m_iItPos = -1; +} + Db::Db() { db_internal::check_error( db_create(&m_pDBP,0,0),"Db::Db" ); + m_pDBHelp = NULL; } @@ -66,6 +500,7 @@ Db::~Db() // TODO: add assert } + delete m_pDBHelp; } @@ -159,6 +594,7 @@ Dbt::Dbt(void *data_arg, u_int32_t size_arg) this->set_size(size_arg); } +/* Dbt::Dbt(const Dbt & other) { using namespace std; @@ -178,6 +614,7 @@ Dbt& Dbt::operator = (const Dbt & other) } return *this; } +*/ Dbt::~Dbt() { diff --git a/xmlhelp/source/cxxhelp/provider/db.hxx b/xmlhelp/source/cxxhelp/provider/db.hxx index fd9e07760a50..7633e78b3425 100644 --- a/xmlhelp/source/cxxhelp/provider/db.hxx +++ b/xmlhelp/source/cxxhelp/provider/db.hxx @@ -36,6 +36,9 @@ #include <berkeleydb/db.h> #endif +#include "com/sun/star/ucb/XSimpleFileAccess.hpp" + +#include <hash_map> #include <rtl/string.hxx> extern "C" { @@ -75,16 +78,106 @@ namespace berkeleydbproxy { { return what_.getStr(); } }; + struct eq + { + bool operator()( const rtl::OString& rKey1, const rtl::OString& rKey2 ) const + { return rKey1.compareTo( rKey2 ) == 0; } + }; + + struct ha + { + size_t operator()( const rtl::OString& rName ) const + { return rName.hashCode(); } + }; + + +//#define TEST_DBHELP + + class DBData + { + friend class DBHelp; + + int m_nSize; + char* m_pBuffer; + + void copyToBuffer( const char* pSrcData, int nSize ); + + public: + DBData( void ) + : m_nSize( 0 ) + , m_pBuffer( NULL ) + {} + ~DBData() + { delete m_pBuffer; } + + int getSize() const + { return m_nSize; } + const char* getData() const + { return m_pBuffer; } + }; + + typedef std::hash_map< rtl::OString,std::pair<int,int>,ha,eq > StringToValPosMap; + typedef std::hash_map< rtl::OString,rtl::OString,ha,eq > StringToDataMap; + + class DBHelp + { + rtl::OUString m_aFileName; + StringToDataMap* m_pStringToDataMap; + StringToValPosMap* m_pStringToValPosMap; + com::sun::star::uno::Reference< com::sun::star::ucb::XSimpleFileAccess > + m_xSFA; + + com::sun::star::uno::Sequence< sal_Int8 > + m_aItData; + const char* m_pItData; + int m_nItRead; + int m_iItPos; + + bool implReadLenAndData( const char* pData, int& riPos, DBData& rValue ); + + public: + DBHelp( const rtl::OUString& rFileName, + com::sun::star::uno::Reference< com::sun::star::ucb::XSimpleFileAccess > xSFA ) + : m_aFileName( rFileName ) + , m_pStringToDataMap( NULL ) + , m_pStringToValPosMap( NULL ) + , m_xSFA( xSFA ) + , m_pItData( NULL ) + , m_nItRead( -1 ) + , m_iItPos( -1 ) + {} + ~DBHelp() + { releaseHashMap(); } + + void createHashMap( bool bOptimizeForPerformance = false ); + void releaseHashMap( void ); + +#ifdef TEST_DBHELP + bool testAgainstDb( const rtl::OString& fileName, bool bOldDbAccess ); +#endif + + bool getValueForKey( const rtl::OString& rKey, DBData& rValue ); + + bool startIteration( void ); + bool getNextKeyAndValue( DBData& rKey, DBData& rValue ); + void stopIteration( void ); + }; class Db : db_internal::Noncopyable { private: DB* m_pDBP; + DBHelp* m_pDBHelp; public: Db(); ~Db(); + void setDBHelp( DBHelp* pDBHelp ) + { m_pDBHelp = pDBHelp; } + DBHelp* getDBHelp( void ) + { return m_pDBHelp; } + int close(u_int32_t flags); int open(DB_TXN *txnid, @@ -126,8 +219,8 @@ namespace berkeleydbproxy { Dbt(void *data_arg, u_int32_t size_arg); Dbt(); - Dbt(const Dbt & other); - Dbt & operator=(const Dbt & other); + //Dbt(const Dbt & other); + //Dbt & operator=(const Dbt & other); ~Dbt(); diff --git a/xmlhelp/source/cxxhelp/provider/resultsetforquery.cxx b/xmlhelp/source/cxxhelp/provider/resultsetforquery.cxx index 4fef867ee6fc..5a16b3a8d8f8 100644 --- a/xmlhelp/source/cxxhelp/provider/resultsetforquery.cxx +++ b/xmlhelp/source/cxxhelp/provider/resultsetforquery.cxx @@ -152,7 +152,9 @@ ResultSetForQuery::ResultSetForQuery( const uno::Reference< lang::XMultiServiceF bool bExtension = false; int iDir = 0; vector< vector<HitItem>* > aIndexFolderResultVectorVector; - while( (idxDir = aIndexFolderIt.nextIndexFolder( bExtension )).getLength() > 0 ) + + bool bTemporary; + while( (idxDir = aIndexFolderIt.nextIndexFolder( bExtension, bTemporary )).getLength() > 0 ) { vector<HitItem> aIndexFolderResultVector; @@ -336,6 +338,9 @@ ResultSetForQuery::ResultSetForQuery( const uno::Reference< lang::XMultiServiceF ++iDir; + if( bTemporary ) + aIndexFolderIt.deleteTempIndexFolder( idxDir ); + } // Iterator diff --git a/xmlhelp/source/cxxhelp/provider/urlparameter.cxx b/xmlhelp/source/cxxhelp/provider/urlparameter.cxx index 6c17cd6dd847..4e7e2efb2a84 100644 --- a/xmlhelp/source/cxxhelp/provider/urlparameter.cxx +++ b/xmlhelp/source/cxxhelp/provider/urlparameter.cxx @@ -303,7 +303,11 @@ void URLParameter::readBerkeley() DataBaseIterator aDbIt( *m_pDatabases, aModule, aLanguage, false ); bool bSuccess = false; + int nSize = 0; + const sal_Char* pData = NULL; + Dbt data; + DBData aDBData; rtl::OUString aExtensionPath; while( true ) { @@ -312,21 +316,36 @@ void URLParameter::readBerkeley() break; rtl::OString keyStr( m_aId.getStr(),m_aId.getLength(),RTL_TEXTENCODING_UTF8 ); - Dbt key( static_cast< void* >( const_cast< sal_Char* >( keyStr.getStr() ) ), - keyStr.getLength() ); - int err = db->get( 0,&key,&data,0 ); - if( err == 0 ) + DBHelp* pDBHelp = db->getDBHelp(); + if( pDBHelp != NULL ) { - bSuccess = true; - break; + bSuccess = pDBHelp->getValueForKey( keyStr, aDBData ); + if( bSuccess ) + { + nSize = aDBData.getSize(); + pData = aDBData.getData(); + break; + } + } + else + { + Dbt key( static_cast< void* >( const_cast< sal_Char* >( keyStr.getStr() ) ), + keyStr.getLength() ); + int err = db->get( 0,&key,&data,0 ); + if( err == 0 ) + { + bSuccess = true; + nSize = data.get_size(); + pData = static_cast<sal_Char*>( data.get_data() ); + break; + } } } if( bSuccess ) { - DbtToStringConverter converter( static_cast< sal_Char* >( data.get_data() ), - data.get_size() ); + DbtToStringConverter converter( pData, nSize ); m_aTitle = converter.getTitle(); m_pDatabases->replaceName( m_aTitle ); m_aPath = converter.getFile(); @@ -1034,12 +1053,6 @@ InputStreamTransformer::InputStreamTransformer( URLParameter* urlParam, rtl::OUString aOUExpandedExtensionPath = Databases::expandURL( aExtensionPath, xContext ); rtl::OString aExpandedExtensionPath = rtl::OUStringToOString( aOUExpandedExtensionPath, osl_getThreadTextEncoding() ); - // Add extension language part - rtl::OString aExtensionLanguage = aPureLanguage; - if( aExtensionLanguage.getLength() > 2 ) - aExtensionLanguage = aExtensionLanguage.copy( 0, 2 ); - aExpandedExtensionPath += rtl::OString('/'); - aExpandedExtensionPath += aExtensionLanguage; parString[last++] = "ExtensionPath"; parString[last++] = rtl::OString('\'') + aExpandedExtensionPath + rtl::OString('\''); diff --git a/xmlhelp/source/treeview/tvread.cxx b/xmlhelp/source/treeview/tvread.cxx index 63f6d4649aa7..62ec993e485d 100644 --- a/xmlhelp/source/treeview/tvread.cxx +++ b/xmlhelp/source/treeview/tvread.cxx @@ -55,6 +55,7 @@ #include <com/sun/star/util/XMacroExpander.hpp> #include <com/sun/star/uri/XUriReferenceFactory.hpp> #include <com/sun/star/uri/XVndSunStarExpandUrl.hpp> +#include <comphelper/locale.hxx> namespace treeview { @@ -967,13 +968,11 @@ void TVChildTarget::subst( const Reference< XMultiServiceFactory >& m_xSMgr, 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" ) ); ExtensionIteratorBase::ExtensionIteratorBase( const rtl::OUString& aLanguage ) : m_eState( USER_EXTENSIONS ) , m_aLanguage( aLanguage ) - , m_aCorrectedLanguage( aLanguage ) { init(); } @@ -1119,6 +1118,44 @@ Reference< deployment::XPackage > ExtensionIteratorBase::implGetNextSharedHelpPa return xHelpPackage; } +inline bool isLetter( sal_Unicode c ) +{ + bool bLetter = ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')); + return bLetter; +} + +void ExtensionIteratorBase::implGetLanguageVectorFromPackage( ::std::vector< ::rtl::OUString > &rv, + com::sun::star::uno::Reference< com::sun::star::deployment::XPackage > xPackage ) +{ + rv.clear(); + rtl::OUString aExtensionPath = xPackage->getURL(); + Sequence< rtl::OUString > aEntrySeq = m_xSFA->getFolderContents( aExtensionPath, true );
+ + const rtl::OUString* pSeq = aEntrySeq.getConstArray(); + sal_Int32 nCount = aEntrySeq.getLength(); + for( sal_Int32 i = 0 ; i < nCount ; ++i ) + { + rtl::OUString aEntry = pSeq[i]; + if( m_xSFA->isFolder( aEntry ) ) + { + sal_Int32 nLastSlash = aEntry.lastIndexOf( '/' ); + if( nLastSlash != -1 ) + { + rtl::OUString aPureEntry = aEntry.copy( nLastSlash + 1 ); + + // Check language sceme + int nLen = aPureEntry.getLength(); + const sal_Unicode* pc = aPureEntry.getStr(); + bool bStartCanBeLanguage = ( nLen >= 2 && isLetter( pc[0] ) && isLetter( pc[1] ) ); + bool bIsLanguage = bStartCanBeLanguage && + ( nLen == 2 || (nLen == 5 && pc[2] == '-' && isLetter( pc[3] ) && isLetter( pc[4] )) ); + if( bIsLanguage ) + rv.push_back( aPureEntry ); + } + } + }
+} + //=================================================================== // class TreeFileIterator @@ -1212,7 +1249,7 @@ rtl::OUString TreeFileIterator::implGetTreeFileFromPackage ( sal_Int32& rnFileSize, Reference< deployment::XPackage > xPackage ) { rtl::OUString aRetFile; - rtl::OUString aLanguage = m_aCorrectedLanguage; + rtl::OUString aLanguage = m_aLanguage; for( sal_Int32 iPass = 0 ; iPass < 2 ; ++iPass ) { rtl::OUStringBuffer aStrBuf; @@ -1228,9 +1265,18 @@ rtl::OUString TreeFileIterator::implGetTreeFileFromPackage { if( m_xSFA->exists( aRetFile ) ) break; - if( m_aCorrectedLanguage.equals( aEnglishFallbackLang ) ) - break; - aLanguage = aEnglishFallbackLang; + + ::std::vector< ::rtl::OUString > av; + implGetLanguageVectorFromPackage( av, xPackage ); + ::std::vector< ::rtl::OUString >::const_iterator pFound = av.end(); + try
+ {
+ pFound = ::comphelper::Locale::getFallback( av, m_aLanguage );
+ }
+ catch( ::comphelper::Locale::MalFormedLocaleException& ) + {} + if( pFound != av.end() )
+ aLanguage = *pFound;
} } diff --git a/xmlhelp/source/treeview/tvread.hxx b/xmlhelp/source/treeview/tvread.hxx index 02d914baeff8..e96e09ed97f0 100644 --- a/xmlhelp/source/treeview/tvread.hxx +++ b/xmlhelp/source/treeview/tvread.hxx @@ -350,6 +350,8 @@ namespace treeview { ( com::sun::star::uno::Reference< com::sun::star::deployment::XPackage >& o_xParentPackageBundle ); com::sun::star::uno::Reference< com::sun::star::deployment::XPackage > implGetNextSharedHelpPackage ( com::sun::star::uno::Reference< com::sun::star::deployment::XPackage >& o_xParentPackageBundle ); + void implGetLanguageVectorFromPackage( ::std::vector< ::rtl::OUString > &rv, + com::sun::star::uno::Reference< com::sun::star::deployment::XPackage > xPackage ); osl::Mutex m_aMutex; com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > m_xContext; @@ -357,7 +359,6 @@ namespace treeview { IteratorState m_eState; rtl::OUString m_aLanguage; - rtl::OUString m_aCorrectedLanguage; com::sun::star::uno::Sequence< com::sun::star::uno::Reference < com::sun::star::deployment::XPackage > > m_aUserPackagesSeq; |