rev 7694 - in kde-extras/strigi: tags tags/0.5.6-1/debian/patches trunk/debian/patches

Fathi Boudra fboudra-guest at alioth.debian.org
Sun Oct 28 14:05:27 UTC 2007


Author: fboudra-guest
Date: 2007-10-28 14:05:27 +0000 (Sun, 28 Oct 2007)
New Revision: 7694

Added:
   kde-extras/strigi/tags/0.5.6-1/
   kde-extras/strigi/tags/0.5.6-1/debian/patches/01_strigi_branch_r727526.diff
   kde-extras/strigi/trunk/debian/patches/01_strigi_branch_r727526.diff
Log:
* Already uploaded. Tags strigi 0.5.6-1.



Copied: kde-extras/strigi/tags/0.5.6-1 (from rev 7693, kde-extras/strigi/trunk)

Added: kde-extras/strigi/tags/0.5.6-1/debian/patches/01_strigi_branch_r727526.diff
===================================================================
--- kde-extras/strigi/tags/0.5.6-1/debian/patches/01_strigi_branch_r727526.diff	                        (rev 0)
+++ kde-extras/strigi/tags/0.5.6-1/debian/patches/01_strigi_branch_r727526.diff	2007-10-28 14:05:27 UTC (rev 7694)
@@ -0,0 +1,4864 @@
+--- a/cmake/FindCppUnit.cmake
++++ b/cmake/FindCppUnit.cmake
+@@ -7,7 +7,9 @@
+ 
+ include (MacroEnsureVersion)
+ 
+-SET(CPPUNIT_MIN_VERSION 1.12.0)
++if(NOT CPPUNIT_MIN_VERSION)
++  SET(CPPUNIT_MIN_VERSION 1.12.0)
++endif(NOT CPPUNIT_MIN_VERSION)
+ 
+ FIND_PROGRAM(CPPUNIT_CONFIG_EXECUTABLE cppunit-config )
+ 
+--- a/cmake/FindHyperEstraier.cmake
++++ b/cmake/FindHyperEstraier.cmake
+@@ -8,7 +8,7 @@
+ #
+ 
+ # find estconfig executable
+-FIND_PROGRAM(ESTCONFIG NAMES estconfig PATHS /bin /usr/bin /usr/local/bin )
++FIND_PROGRAM(ESTCONFIG NAMES estconfig PATHS /bin )
+ 
+ # get configuration options
+ IF (ESTCONFIG)
+--- a/config.h.cmake
++++ b/config.h.cmake
+@@ -147,7 +147,34 @@
+ 
+ #define LIBINSTALLDIR "${LIBINSTALLDIR}"
+ 
++#define SOURCEDIR "${CMAKE_SOURCE_DIR}"
++
++#define BINARYDIR "${CMAKE_BINARY_DIR}"
++
+ #define INSTALLDIR "${CMAKE_INSTALL_PREFIX}"
+ 
+ #define MIMEINSTALLDIR "${MIMEINSTALLDIR}"
++
++// Definition of types that are used internally
++
++#if !@HAVE_INTPTR_T@
++ typedef int intptr_t;
++ #define HAVE_INTPTR_T 1
++#endif
++
++#if !@HAVE_SOCKLEN_T@
++ typedef int socklen_t;
++ #define HAVE_SOCKLEN_T 1
++#endif
++
++#if !@HAVE_SSIZE_T@
++ #ifndef _SSIZE_T_DEFINED 
++  #ifndef HAVE_SSIZE_T
++   typedef signed int ssize_t;
++   #define HAVE_SSIZE_T 1
++  #endif
++  #define _SSIZE_T_DEFINED 1    // kdewin32 define
++ #endif
++#endif
++
+ #endif //CONFIG_H
+--- a/src/CMakeLists.txt
++++ b/src/CMakeLists.txt
+@@ -2,7 +2,6 @@
+ # Check copied from kdelibs FindX11.cmake.
+ CHECK_LIBRARY_EXISTS("socket" "connect" "" CMAKE_LIB_SOCKET_HAS_CONNECT)
+ 
+-
+ set(DIRS streams streamanalyzer archivereader xsd dummyindexer xmlindexer combinedindexer indexertests strigicmd)
+ 
+ if (CLucene_FOUND)
+@@ -11,32 +10,31 @@
+ 
+ if (HyperEstraier_FOUND)
+   set(DIRS ${DIRS} estraierindexer)
+-  message("** HyperEstraier support is experimental. **")
++  message("** HyperEstraier support is broken. Do not rely on it. **")
+ endif (HyperEstraier_FOUND)
+ 
+ if (SQLite_FOUND)
+   set(DIRS ${DIRS} sqliteindexer)
+-  message("** SQLite support is experimental. **")
++  message("** SQLite support is broken. Do not rely on it. **")
+ endif (SQLite_FOUND)
+ 
+-if (CLucene_FOUND OR HyperEstraier_FOUND OR SQLite_FOUND)
+-  if(NOT WIN32)
+-     set(DIRS ${DIRS} htmlgui)
+-  endif(NOT WIN32)
+-  # searchclient needs htmlgui which is not compilable on win32
+-  if (QT_QTDBUS_FOUND AND NOT WIN32)
+-     set(DIRS ${DIRS} searchclient)
+-  endif (QT_QTDBUS_FOUND AND NOT WIN32)
+-  # make sure we build the daemon on all architectures - not as long as sys/socket.h is used
+-  if(NOT WIN32)
+-    set(DIRS ${DIRS} daemon)
+-  endif(NOT WIN32)
+-  message(STATUS "Index libraries were found. strigidaemon will be built.")
+-else (CLucene_FOUND OR HyperEstraier_FOUND OR SQLite_FOUND)
+-  message("** No index libraries were found. strigidaemon will not be built.")
++if(NOT WIN32)
++  set(DIRS ${DIRS} htmlgui)
++endif(NOT WIN32)
++# searchclient needs htmlgui which is not compilable on win32
++if (QT_QTDBUS_FOUND AND NOT WIN32)
++  set(DIRS ${DIRS} searchclient)
++endif (QT_QTDBUS_FOUND AND NOT WIN32)
++# make sure we build the daemon on all architectures - not as long as sys/socket.h is used
++if(NOT WIN32)
++  set(DIRS ${DIRS} daemon)
++endif(NOT WIN32)
++
++if (NOT CLucene_FOUND)
++  message("** No CLucene libraries were found, so Strigi cannot use indexes.")
+   message("** It is recommended to install CLucene >= 0.9.16.")
+   message("** You will still be able to use deepfind, deepgrep and xmlindexer.")
+-endif (CLucene_FOUND OR HyperEstraier_FOUND OR SQLite_FOUND)
++endif (NOT CLucene_FOUND)
+ 
+ if (QT4_FOUND)
+   set(DIRS ${DIRS} archiveengine qclient)
+--- a/src/combinedindexer/CMakeLists.txt
++++ b/src/combinedindexer/CMakeLists.txt
+@@ -4,29 +4,7 @@
+ 	${strigi_BINARY_DIR}/src/streams
+ 	${strigi_SOURCE_DIR}/src/streams/strigi)
+ 
+-if (CLucene_FOUND)
+-    add_definitions(-DHAVE_CLUCENE)
+-    set(combinedindex_LIBS ${combinedindex_LIBS} cluceneindex)
+-    include_directories( ../luceneindexer )
+-endif (CLucene_FOUND)
+-
+-if (HyperEstraier_FOUND)
+-    add_definitions(-DHAVE_ESTRAIER)
+-    set(combinedindex_LIBS ${combinedindex_LIBS} estraierindex)
+-    include_directories( ../estraierindexer )
+-endif (HyperEstraier_FOUND)
+-
+-if (SQLite_FOUND)
+-    add_definitions(-DHAVE_SQLITE)
+-    set(combinedindex_LIBS ${combinedindex_LIBS} sqliteindex)
+-    include_directories( ../sqliteindexer )
+-endif (SQLite_FOUND)
+-
+ add_library(combinedindex combinedindexmanager.cpp)
+ 
+ target_link_libraries(combinedindex streamanalyzer grepindex
+     ${combinedindex_LIBS})
+-
+-#add_executable(combinedindexer combinedindexer.cpp)
+-#target_link_libraries(combinedindexer combinedindex filters)
+-
+--- a/src/combinedindexer/combinedindexmanager.cpp
++++ b/src/combinedindexer/combinedindexmanager.cpp
+@@ -21,6 +21,7 @@
+ #include <strigi/strigiconfig.h>
+ #include "variant.h"
+ 
++/*
+ #include "grepindexmanager.h"
+ #ifdef HAVE_CLUCENE
+ #include "cluceneindexmanager.h"
+@@ -34,20 +35,26 @@
+ #ifdef HAVE_SQLITE
+ #include "sqliteindexmanager.h"
+ #endif
++*/
+ 
+ #include "tssptr.h"
+ #include "query.h"
+ #include "indexeddocument.h"
+ #include "indexreader.h"
++#include "indexpluginloader.h"
+ #include <string>
+ #include <set>
+ #include <map>
+ using namespace std;
+ using namespace Strigi;
+ 
++/*
+ map<string, IndexManager*(*)(const char*)>
+ CombinedIndexManager::factories() {
+     map<string, IndexManager*(*)(const char*)> factories;
++    //IndexPluginLoader pluginloader;
++    //factories = pluginloader.factories();
++
+ #ifdef HAVE_ESTRAIER
+     factories["estraier"] = createEstraierIndexManager;
+ #endif
+@@ -74,7 +81,7 @@
+     }
+     return v;
+ }
+-
++*/
+ class CombinedIndexReader : public IndexReader {
+ private:
+     CombinedIndexManager* m;
+@@ -119,19 +126,21 @@
+ }
+ CombinedIndexManager::Private::~Private() {
+     if (writermanager) {
+-        delete writermanager;
++        IndexPluginLoader::deleteIndexManager(writermanager);
+     }
+ }
+ CombinedIndexManager::CombinedIndexManager(const string& type,
+         const string& indexdir) :p(new CombinedIndexManager::Private(this)) {
++    p->writermanager = IndexPluginLoader::createIndexManager(type.c_str(),
++        indexdir.c_str());
+     // determine the right index manager
+-    map<string, IndexManager*(*)(const char*)> l_factories = factories();
++/*    map<string, IndexManager*(*)(const char*)> l_factories = factories();
+     map<string, IndexManager*(*)(const char*)>::const_iterator f
+         = l_factories.find(type);
+     if (f == l_factories.end()) {
+         f = l_factories.begin();
+     }
+-    p->writermanager = f->second(indexdir.c_str());
++    p->writermanager = f->second(indexdir.c_str());*/
+ }
+ CombinedIndexManager::~CombinedIndexManager() {
+     delete p;
+@@ -148,14 +157,12 @@
+ CombinedIndexManager::addReadonlyIndex(const string& indexdir,
+         const string& type) {
+     removeReadonlyIndex(indexdir);
+-    // determine the right index manager
+-    map<string, IndexManager*(*)(const char*)> l_factories = factories();
+-    map<string, IndexManager*(*)(const char*)>::const_iterator f
+-        = l_factories.find(type);
+-    if (f == l_factories.end()) {
++
++    IndexManager* im = IndexPluginLoader::createIndexManager(type.c_str(),
++        indexdir.c_str());
++    if (im == 0) {
+         return;
+     }
+-    IndexManager* im = f->second(indexdir.c_str());
+     p->lock.lock();
+     p->readmanagers[indexdir] = im;
+     p->lock.unlock();
+--- a/src/combinedindexer/combinedindexmanager.h
++++ b/src/combinedindexer/combinedindexmanager.h
+@@ -40,10 +40,6 @@
+ 
+     void addReadonlyIndex(const std::string& indexdir, const std::string& type);
+     void removeReadonlyIndex(const std::string& indexdir);
+-
+-    static std::map<std::string, Strigi::IndexManager*(*)(const char*)>
+-        factories();
+-    static std::vector<std::string> backEnds();
+ };
+ 
+ #endif
+--- a/src/combinedindexer/tssptr.h
++++ b/src/combinedindexer/tssptr.h
+@@ -19,6 +19,7 @@
+  */
+ 
+ #include "strigi_thread.h"
++#include "indexpluginloader.h"
+ 
+ // thread safe smart pointer
+ template <class T>
+@@ -61,7 +62,7 @@
+             int c = --(p->count);
+             p->lock.unlock();
+             if (c == 0) {
+-                delete p->p;
++                Strigi::IndexPluginLoader::deleteIndexManager(p->p);
+                 delete p;
+             }
+             p = 0;
+--- a/src/daemon/daemon.cpp
++++ b/src/daemon/daemon.cpp
+@@ -21,6 +21,7 @@
+ #include "interface.h"
+ #include "daemonconfigurator.h"
+ #include "combinedindexmanager.h"
++#include "indexpluginloader.h"
+ 
+ #include "indexscheduler.h"
+ #include "analyzerconfiguration.h"
+@@ -151,7 +152,7 @@
+ }
+ void
+ printBackendList() {
+-    std::vector<std::string> backends = CombinedIndexManager::backEnds();
++    std::vector<std::string> backends = IndexPluginLoader::indexNames();
+     for ( unsigned int i = 0; i < backends.size(); ++i ) {
+         printf( "%s\n", backends[i].c_str() );
+     }
+@@ -194,7 +195,7 @@
+ }
+ void
+ ensureBackend( const std::string& backendName ) {
+-    std::vector<std::string> backends = CombinedIndexManager::backEnds();
++    std::vector<std::string> backends = IndexPluginLoader::indexNames();
+     if ( std::find( backends.begin(), backends.end(), backendName ) == backends.end() ) {
+         fprintf( stderr, "Unknown backend type: %s\n", backendName.c_str() );
+         exit( 2 );
+--- a/src/daemon/eventlistener/inotifylistener.cpp
++++ b/src/daemon/eventlistener/inotifylistener.cpp
+@@ -39,6 +39,38 @@
+ using namespace std;
+ using namespace Strigi;
+ 
++namespace {
++    /*!
++    * @param path string containing path to check
++    * Appends the terminating char to path.
++    * Under Windows that char is '\', '/' under *nix
++    */
++    string fixPath (string path)
++    {
++        if ( path.c_str() == NULL || path.length() == 0 )
++            return "";
++
++        string temp(path);
++
++    #ifdef HAVE_WINDOWS_H
++        size_t l= temp.length();
++        char* t = (char*)temp.c_str();
++        for (size_t i=0;i<l;i++){
++            if ( t[i] == '\\' )
++                t[i] = '/';
++        }
++        temp[0] = tolower(temp.at(0));
++    #endif
++
++        char separator = '/';
++
++        if (temp[temp.length() - 1 ] != separator)
++            temp += separator;
++
++        return temp;
++    }
++}
++
+ class MatchString {
+     string m_fixed_val;
+ 
+@@ -345,59 +377,38 @@
+     m_toWatch.clear();
+     m_toIndex.clear();
+     
+-    Strigi::FileLister lister (m_pindexerconfiguration);
+-    
+     for (set<string>::iterator iter = m_newDirs.begin();
+          iter != m_newDirs.end(); iter++)
+     {
+-        string filename;
+-        time_t mTime;
+-        
+-        lister.startListing( *iter);
+-        
+-        while (lister.nextFile( filename, mTime) != -1)
+-            m_toIndex.insert (make_pair (filename, mTime));
+-
+-        //TODO: look for a better solution
+-        set<string> temp = lister.getListedDirs();
+-        for (set<string>::iterator it = temp.begin(); it != temp.end(); it++)
+-            m_toWatch.insert(*it);
+-    }
+-    
+-    map <string, time_t> indexedFiles = m_pManager->indexReader()->files(0);
+-    map<string,time_t>::iterator mi = indexedFiles.begin();
+-
+-    while (mi != indexedFiles.end()) {
+-        map<string,time_t>::iterator it = m_toIndex.find(mi->first);
+-
+-        if (it == m_toIndex.end()) {
+-            // file has been deleted since last run
+-            m_events.push_back (new Event (Event::DELETED, mi->first));
++        DirLister lister(m_pindexerconfiguration);
++        string path;
++        vector<pair<string, struct stat> > dirs;
++
++        lister.startListing (*iter);
++        int ret = lister.nextDir(path, dirs);
++
++        while (ret != -1) {
++            for (vector<pair<string, struct stat> >::iterator iter = dirs.begin();
++                 iter != dirs.end(); iter++)
++            {
++                struct stat stats = iter->second;
+ 
+-            // no more useful, speedup into dirsRemoved
+-            map<string,time_t>::iterator itrm = mi;
+-            mi++;
+-            indexedFiles.erase(itrm);
+-        }
+-        else if (mi->second < it->second) {
+-            // file has been updated since last run
+-            m_events.push_back (new Event (Event::UPDATED, mi->first));
+-            m_toIndex.erase (it);
+-            mi++;
+-        }
+-        else {
+-            // file has NOT been changed since last run,
+-            // we keep our indexed information
+-            m_toIndex.erase (it);
+-            mi++;
++                if (S_ISDIR(stats.st_mode)) {
++                    //dir
++                    m_toWatch.insert (iter->first);
++                }
++                else if (S_ISREG(stats.st_mode)) {
++                    //file
++                    m_events.push_back (new Event (Event::CREATED, iter->first));
++                }
++            }
++            ret = lister.nextDir(path, dirs);
+         }
+     }
+ 
+-    // now m_toIndex contains only files created since the last run
+-    for (mi = m_toIndex.begin(); mi != m_toIndex.end(); mi++)
+-        m_events.push_back (new Event (Event::CREATED, mi->first));
+-
+     m_nomoreIndexedDirs.clear();
++    set<string> alreadyWatched;
++    
+     for (map<int, string>::iterator it = watchedDirs.begin();
+          it != watchedDirs.end(); it++)
+     {
+@@ -405,7 +416,68 @@
+         if (match == m_toWatch.end()) // dir is no longer watched
+             m_nomoreIndexedDirs.insert(it->second);
+         else // dir is already watched
+-            m_toWatch.erase (match);
++            alreadyWatched.insert (*match);
++    }
++
++    // look for updated dirs
++    m_toIndex.clear();
++    for (set<string>::iterator iter = alreadyWatched.begin();
++         iter != alreadyWatched.end(); iter++)
++    {
++        // retrieve files contained into the already watched dirs
++
++        Strigi::DirLister lister (m_pindexerconfiguration);
++
++        lister.startListing (*iter);
++
++        string path;
++        vector<pair<string, struct stat> > dirs;
++        int ret = lister.nextDir(path, dirs);
++
++        while (ret != -1) {
++            cout << "path = " << path << endl;
++
++            for (vector<pair<string, struct stat> >::iterator iter = dirs.begin();
++                 iter != dirs.end(); iter++)
++            {
++                struct stat stats = iter->second;
++                if (S_ISREG(stats.st_mode))
++                    m_toIndex.insert (make_pair (iter->first, stats.st_mtime));
++            }
++            ret = lister.nextDir(path, dirs);
++        }
++
++        map <string, time_t> indexedFiles;
++        m_pManager->indexReader()->getChildren (*iter, indexedFiles);
++        for (map<string, time_t>::iterator iter = m_toIndex.begin();
++             iter != m_toIndex.end(); iter++)
++        {
++            map<string, time_t>::iterator match;
++            match = indexedFiles.find(iter->first);
++            if (match == indexedFiles.end()) {
++                // new file created
++                m_events.push_back (new Event (Event::CREATED, iter->first));
++            }
++            else if (match->second < iter->second) {
++                // file has been updated
++                m_events.push_back (new Event (Event::UPDATED, iter->first));
++            }
++        }
++        m_toIndex.clear();
++    }
++
++    // remove no more indexed items
++    for (set<string>::iterator iter = m_nomoreIndexedDirs.begin();
++         iter != m_nomoreIndexedDirs.end(); iter++)
++    {
++        map <string, time_t> indexedFiles;
++        m_pManager->indexReader()->getChildren (*iter, indexedFiles);
++
++        for (map<string,time_t>::iterator mi = indexedFiles.begin();
++             mi != indexedFiles.end(); mi++)
++        {
++            m_events.push_back (new Event (Event::DELETED, mi->first));
++        }
+     }
+     
+     if (testInterrupt()) {
+@@ -738,25 +810,35 @@
+                     // a new directory has been created or an already watched
+                     // directory has been moved into a watched place
+                     
+-                    m_toIndex.clear();
+                     m_toWatch.clear();
+ 
+-                    FileLister lister(m_pindexerconfiguration);
+-                    
+-                    string filename;
+-                    time_t mTime;
+-                    while (lister.nextFile( filename, mTime) != -1)
+-                        m_toIndex.insert (make_pair (filename, mTime));
+-
+-                    m_toWatch = lister.getListedDirs();
+-
+-                    for (map<string,time_t>::iterator i = m_toIndex.begin();
+-                         i != m_toIndex.end(); i++)
+-                    {
+-                        Event* event = new Event (Event::CREATED, i->first);
+-                        events.push_back (event);
++                    DirLister lister(m_pindexerconfiguration);
++                    string path;
++                    vector<pair<string, struct stat> > dirs;
++
++                    lister.startListing (file);
++                    int ret = lister.nextDir(path, dirs);
++
++                    while (ret != -1) {
++                        for (vector<pair<string, struct stat> >::iterator iter = dirs.begin();
++                             iter != dirs.end(); iter++)
++                        {
++                            struct stat stats = iter->second;
++                            
++                            if (S_ISDIR(stats.st_mode)) {
++                                //dir
++                                m_toWatch.insert (iter->first);
++                            }
++                            else if (S_ISREG(stats.st_mode)) {
++                                //file
++                                Event* event = new Event (Event::CREATED,
++                                                          iter->first);
++                                events.push_back (event);
++                            }
++                        }
++                        ret = lister.nextDir(path, dirs);
+                     }
+-
++                    
+                     // add new watches
+                     addWatches (m_toWatch);
+ 
+@@ -1066,8 +1148,9 @@
+     // we've to de-index all files contained into the deleted/moved directory
+     if (m_pManager)
+     {
+-        // all indexed files
+-        map<string, time_t> indexedFiles = m_pManager->indexReader()->files(0);
++        // all indexed files contained into dir
++        map<string, time_t> indexedFiles;
++        m_pManager->indexReader()->getChildren(dir, indexedFiles);
+ 
+         // remove all entries that were contained into the removed dir
+         for (map<string, time_t>::iterator it = indexedFiles.begin();
+@@ -1076,12 +1159,8 @@
+             if (enableInterrupt && testInterrupt())
+                 break;
+             
+-            string::size_type pos = (it->first).find (dir);
+-            if (pos == 0)
+-            {
+-                Event* event = new Event (Event::DELETED, it->first);
+-                newEvents.push_back (event);
+-            }
++            Event* event = new Event (Event::DELETED, it->first);
++            newEvents.push_back (event);
+         }
+     }
+     else
+--- a/src/daemon/eventlistener/pollinglistener.cpp
++++ b/src/daemon/eventlistener/pollinglistener.cpp
+@@ -38,6 +38,38 @@
+ using namespace std;
+ using namespace Strigi;
+ 
++namespace {
++    /*!
++    * @param path string containing path to check
++    * Appends the terminating char to path.
++    * Under Windows that char is '\', '/' under *nix
++    */
++    string fixPath (string path)
++    {
++        if ( path.c_str() == NULL || path.length() == 0 )
++            return "";
++
++        string temp(path);
++
++    #ifdef HAVE_WINDOWS_H
++        size_t l= temp.length();
++        char* t = (char*)temp.c_str();
++        for (size_t i=0;i<l;i++){
++            if ( t[i] == '\\' )
++                t[i] = '/';
++        }
++        temp[0] = tolower(temp.at(0));
++    #endif
++
++        char separator = '/';
++
++        if (temp[temp.length() - 1 ] != separator)
++            temp += separator;
++
++        return temp;
++    }
++}
++
+ PollingListener::PollingListener() :EventListener("PollingListener") {
+     setState(Idling);
+     STRIGI_MUTEX_INIT(&m_mutex);
+@@ -123,35 +155,7 @@
+ 
+     STRIGI_MUTEX_UNLOCK (&m_mutex);
+ }
+-/*!
+-* @param path string containing path to check
+-* Appends the terminating char to path.
+-* Under Windows that char is '\', '/' under *nix
+-*/
+-string fixPath (string path)
+-{
+-    if ( path.c_str() == NULL || path.length() == 0 )
+-        return "";
+-
+-    string temp(path);
+-
+-#ifdef HAVE_WINDOWS_H
+-    size_t l= temp.length();
+-    char* t = (char*)temp.c_str();
+-    for (size_t i=0;i<l;i++){
+-        if ( t[i] == '\\' )
+-            t[i] = '/';
+-    }
+-    temp[0] = tolower(temp.at(0));
+-#endif
+-
+-    char separator = '/';
+ 
+-    if (temp[temp.length() - 1 ] != separator)
+-        temp += separator;
+-
+-    return temp;
+-}
+ void
+ PollingListener::addWatches(const set<string>& watches, bool enableInterrupt) {
+     for (set<string>::iterator iter = watches.begin();
+--- a/src/daemon/interface.cpp
++++ b/src/daemon/interface.cpp
+@@ -18,9 +18,10 @@
+  * Boston, MA 02110-1301, USA.
+  */
+ #include "interface.h"
+-#include "indexreader.h"
+ #include "combinedindexmanager.h"
++#include "indexreader.h"
+ #include "indexwriter.h"
++#include "indexpluginloader.h"
+ #include "indexscheduler.h"
+ #include "eventlistener.h"
+ #include "streamanalyzer.h"
+@@ -69,7 +70,7 @@
+ }
+ vector<string>
+ Interface::getBackEnds() {
+-    return manager.backEnds();
++    return IndexPluginLoader::indexNames();
+ }
+ map<string, string>
+ Interface::getStatus() {
+--- a/src/estraierindexer/CMakeLists.txt
++++ b/src/estraierindexer/CMakeLists.txt
+@@ -3,15 +3,26 @@
+ include_directories( ../streamanalyzer ../streams ${EST_INCLUDE_DIR}
+ 	${strigi_BINARY_DIR}/src/streams
+ 	${strigi_SOURCE_DIR}/src/streams/strigi)
++link_directories(${EST_LIBDIR})
++set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EST_CFLAGS}")
+ 
+-add_library(estraierindex
++if(WIN32)
++  # this is needed to have mingw, cygwin and msvc libs installed in one directory
++  if(MSVC)
++    set(prefix msvc_strigiindex_)
++  elseif(CYGWIN)
++    set(prefix cyg_strigiindex_)
++  elseif(MINGW)
++    set(prefix mingw_strigiindex_)
++  endif(MSVC)
++else(WIN32)
++  set(prefix strigiindex_)
++endif(WIN32)
++add_library(estraier MODULE
+ 	estraierindexmanager.cpp
+         estraierindexreader.cpp
+ 	estraierindexwriter.cpp
+ )
+-
+-target_link_libraries(estraierindex streamanalyzer ${EST_LIBS})
+-
+-add_executable(estraierindexer estraierindexer.cpp)
+-target_link_libraries(estraierindexer estraierindex)
+-
++set_target_properties(estraier PROPERTIES PREFIX ${prefix})
++target_link_libraries(estraier ${EST_LIBS})
++install(TARGETS estraier LIBRARY DESTINATION ${LIB_DESTINATION}/strigi)
+--- a/src/estraierindexer/estraierindexmanager.cpp
++++ b/src/estraierindexer/estraierindexmanager.cpp
+@@ -22,20 +22,21 @@
+ #include "estraierindexreader.h"
+ #include "estraierindexwriter.h"
+ #include "strigi_thread.h"
++#include "indexplugin.h"
++#include <iostream>
+ #include <assert.h>
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <unistd.h>
++#include <errno.h>
+ #include "stgdirent.h" //our dirent compatibility header... uses native if available
+ using namespace std;
+ using namespace Strigi;
+ 
+-pthread_mutex_t EstraierIndexManager::lock = PTHREAD_MUTEX_INITIALIZER;
++/* define and export the index factory */
++REGISTER_STRIGI_INDEXMANAGER(EstraierIndexManager)
+ 
+-Strigi::IndexManager*
+-createEstraierIndexManager(const char* path) {
+-    return new EstraierIndexManager(path);
+-}
++pthread_mutex_t EstraierIndexManager::lock = PTHREAD_MUTEX_INITIALIZER;
+ 
+ EstraierIndexManager::EstraierIndexManager(const char* dbd)
+         : dblock(lock), dbdir(dbd) {
+--- a/src/estraierindexer/estraierindexmanager.h
++++ b/src/estraierindexer/estraierindexmanager.h
+@@ -56,7 +56,4 @@
+     void deleteIndex();
+ };
+ 
+-Strigi::IndexManager*
+-createEstraierIndexManager(const char* path);
+-
+ #endif
+--- a/src/estraierindexer/estraierindexreader.cpp
++++ b/src/estraierindexer/estraierindexreader.cpp
+@@ -37,7 +37,7 @@
+     // build the phrase string
+ 
+     // write the part of the query that matches the document context
+-    string inphrase, exphrase;
++/*    string inphrase, exphrase;
+     set<string> terms;
+     const map<string, set<string> >& includes = query.includes();
+     map<string, set<string> >::const_iterator i = includes.find("");
+@@ -60,9 +60,9 @@
+             phrase += " ANDNOT ";
+         }
+         phrase += *j;
+-    }
++    } */
+     ESTCOND* cond = est_cond_new();
+-    printf("%s", phrase.c_str());
++/*    printf("%s", phrase.c_str());
+     if (phrase.length() > 0) {
+         est_cond_set_phrase(cond, phrase.c_str());
+     }
+@@ -93,7 +93,7 @@
+             est_cond_add_attr(cond, att.c_str());
+         }
+     }
+-    printf("\n");
++    printf("\n");*/ 
+ 
+     return cond;
+ }
+@@ -136,7 +136,7 @@
+     return n;
+ }
+ vector<IndexedDocument>
+-EstraierIndexReader::query(const Query& query) {
++EstraierIndexReader::query(const Query& query, int off, int max) {
+     ESTCOND* cond = createCondition(query);
+     est_cond_set_max(cond, 10);
+     int n;
+@@ -182,9 +182,17 @@
+     free(ids);
+     return results;
+ }
+-map<string, time_t>
+-EstraierIndexReader::files(char depth) {
+-    map<string, time_t> files;
++void
++EstraierIndexReader::getHits(const Strigi::Query& query,
++        const std::vector<std::string>& fields,
++        const std::vector<Strigi::Variant::Type>& types,
++        std::vector<std::vector<Strigi::Variant> >& result,
++        int off, int max) {
++}
++void
++EstraierIndexReader::getChildren(const std::string& parent,
++            std::map<std::string, time_t>& children) {
++/*    map<string, time_t> files;
+     ESTCOND* cond = est_cond_new();
+     string q = "depth NUMEQ 0";
+     est_cond_add_attr(cond, q.c_str());
+@@ -208,7 +216,7 @@
+     // clean up
+     est_cond_delete(cond);
+     free(ids);
+-    return files;
++    return files;*/
+ }
+ int32_t
+ EstraierIndexReader::countDocuments() {
+@@ -231,16 +239,10 @@
+     manager->deref();
+     return count;
+ }
+-int64_t
+-EstraierIndexReader::documentId(const string& uri) {
+-    ESTDB* db = manager->ref();
+-    int64_t id = est_db_uri_to_id(db, uri.c_str());
+-    manager->deref();
+-    return id;
+-}
+ time_t
+-EstraierIndexReader::mTime(int64_t docid) {
++EstraierIndexReader::mTime(const std::string& uri) {
+     ESTDB* db = manager->ref();
++    int64_t docid = est_db_uri_to_id(db, uri.c_str());
+     time_t mtime = -1;
+     char *cstr = est_db_get_doc_attr(db, docid, "@mdate");
+     if (cstr) {
+@@ -248,12 +250,7 @@
+         free(cstr);
+     }
+     manager->deref();
+-    return mtime;
+-
+-}
+-time_t
+-EstraierIndexReader::mTime(const std::string& uri) {
+-    return mTime(documentId(uri));
++    return docid;
+ }
+ vector<string>
+ EstraierIndexReader::fieldNames() {
+@@ -264,3 +261,14 @@
+             const string& labeltype) {
+     return vector<pair<string,uint32_t> >();
+ }
++int32_t
++EstraierIndexReader::countKeywords(const std::string& keywordprefix,
++        const std::vector<std::string>& fieldnames) {
++    return -1;
++}
++vector<string>
++EstraierIndexReader::keywords(const std::string& keywordmatch,
++        const std::vector<std::string>& fieldnames,
++        uint32_t max, uint32_t offset) {
++    return vector<string>();
++}
+--- a/src/estraierindexer/estraierindexreader.h
++++ b/src/estraierindexer/estraierindexreader.h
+@@ -36,14 +36,14 @@
+     static ESTCOND* createCondition(const Strigi::Query&);
+     static const char* mapId(const std::string& id);
+ public:
++    std::vector<Strigi::IndexedDocument> query(const Strigi::Query&,
++        int off, int max);
++    void getHits(const Strigi::Query& query,
++        const std::vector<std::string>& fields,
++        const std::vector<Strigi::Variant::Type>& types,
++        std::vector<std::vector<Strigi::Variant> >& result,
++        int off, int max);
+     int32_t countHits(const Strigi::Query&);
+-    std::vector<Strigi::IndexedDocument> query(const Strigi::Query&);
+-    std::map<std::string, time_t> files(char depth);
+-    int countDocuments();
+-    int32_t countWords();
+-    int64_t indexSize();
+-    int64_t documentId(const std::string& uri);
+-    time_t mTime(int64_t docid);
+     time_t mTime(const std::string& uri);
+     std::vector<std::string> fieldNames();
+     std::vector<std::pair<std::string,uint32_t> > histogram(
+@@ -54,6 +54,11 @@
+     std::vector<std::string> keywords(const std::string& keywordmatch,
+         const std::vector<std::string>& fieldnames,
+         uint32_t max, uint32_t offset);
++    void getChildren(const std::string& parent,
++            std::map<std::string, time_t>& children);
++    int countDocuments();
++    int32_t countWords();
++    int64_t indexSize();
+ };
+ 
+ #endif
+--- a/src/estraierindexer/estraierindexwriter.cpp
++++ b/src/estraierindexer/estraierindexwriter.cpp
+@@ -49,16 +49,16 @@
+ EstraierIndexWriter::addValue(const AnalysisResult* idx,
+         const RegisteredField* field, const string& value) {
+     ESTDOC* doc = static_cast<ESTDOC*>(idx->writerData());
+-    if (field->getKey() == "size") {
++    if (field->key() == "size") {
+         est_doc_add_attr(doc, "@size", value.c_str());
+-    } else if (field->getKey() == "title") {
++    } else if (field->key() == "title") {
+         est_doc_add_attr(doc, "@title", value.c_str());
+     } else {
+-        est_doc_add_attr(doc, field->getKey().c_str(), value.c_str());
++        est_doc_add_attr(doc, field->key().c_str(), value.c_str());
+     }
+ }
+ void
+-EstraierIndexWriter::startAnalysis(AnalysisResult* idx) {
++EstraierIndexWriter::startAnalysis(const AnalysisResult* idx) {
+     // allocate a new estraier document
+     ESTDOC* doc = est_doc_new();
+     idx->setWriterData(doc);
+--- a/src/estraierindexer/estraierindexwriter.h
++++ b/src/estraierindexer/estraierindexwriter.h
+@@ -31,7 +31,7 @@
+     const std::string indexpath;
+ 
+ protected:
+-    void startAnalysis(Strigi::AnalysisResult*);
++    void startAnalysis(const Strigi::AnalysisResult*);
+     void addValue(const Strigi::AnalysisResult*, const Strigi::RegisteredField* field,
+         const std::string& value);
+     void addValue(const Strigi::AnalysisResult*, const Strigi::RegisteredField* field,
+--- a/src/estraierindexer/tests/CMakeLists.txt
++++ b/src/estraierindexer/tests/CMakeLists.txt
+@@ -1,9 +1,10 @@
+ include_directories(.. ../../indexertests)
++link_directories(${EST_LIBDIR})
+ 
+ CREATE_TEST_SOURCELIST(Tests testrunner.cpp EstraierTest.cpp)
+ 
+ ADD_EXECUTABLE(testrunner ${Tests} )
+-target_link_libraries(testrunner streams estraierindex indexertests)
++target_link_libraries(testrunner streams indexertests)
+ 
+ SET (TestsToRun ${Tests})
+ REMOVE (TestsToRun testrunner.cpp)
+--- a/src/estraierindexer/tests/EstraierTest.cpp
++++ b/src/estraierindexer/tests/EstraierTest.cpp
+@@ -1,5 +1,6 @@
+ #include <strigi/strigiconfig.h>
+-#include "estraierindexmanager.h"
++#include "indexpluginloader.h"
++#include "indexmanager.h"
+ #include "indexmanagertests.h"
+ #include "indexwritertests.h"
+ #include "indexreadertests.h"
+@@ -15,7 +16,8 @@
+ 
+     // initialize a directory for writing and an indexmanager
+     mkdir(path, S_IRUSR|S_IWUSR|S_IXUSR);
+-    EstraierIndexManager* manager = new EstraierIndexManager(path);
++    Strigi::IndexManager *manager
++            = Strigi::IndexPluginLoader::createIndexManager("estraier", path);
+ 
+     Strigi::AnalyzerConfiguration ic;
+     IndexManagerTests tests(manager, ic);
+--- a/src/htmlgui/strigihtmlgui.cpp
++++ b/src/htmlgui/strigihtmlgui.cpp
+@@ -27,6 +27,7 @@
+ #include <dirent.h>
+ #include <sstream>
+ #include <fstream>
++#include <iostream>
+ #include <sys/stat.h>
+ #include <stdlib.h>
+ #include <string.h>
+@@ -56,7 +57,9 @@
+ }
+ void
+ StrigiHtmlGui::printHtmlHeader(ostream& out) {
+-    out << "<?xml version='1.0' encoding='utf-8'?>\n"
++    // FIXME: extra spaces added at the beginning as a wordaround because
++    // KIO discards several first chars for unknown reason
++    out << "                           <?xml version='1.0' encoding='utf-8'?>\n"
+         "<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' "
+         "'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>\n"
+         "<html xmlns='http://www.w3.org/1999/xhtml'>"
+@@ -190,12 +193,15 @@
+     if (i != params.end()) {
+         max = atoi(i->second.c_str());
+     }
+-    if (max == 0) max = 10;
++    if (max <= 0 || max > 1000) max = 10;
+     int off = 0;
+     i = params.find("o");
+     if (i != params.end()) {
+         off = atoi(i->second.c_str());
+     }
++    if (off < 0) {
++        off = 0;
++    }
+     string selectedtab;
+     i = params.find("t");
+     if (i != params.end()) {
+@@ -215,20 +221,23 @@
+         bool doother = true;
+         tabs = readTabQueries();
+         if (tabs.size() == 0) {
+-            tabs["Images"] = "content.mime_type:image*";
+-            tabs["Mail"] = "content.mime_type:message/*";
+-            tabs["Web"] = "content.mime_type:text/html";
+-            tabs["Text"] = "content.mime_type:text/*";
++            tabs["Images"] = "mimeType:image*";
++            tabs["Mail"] = "mimeType:message/*";
++            tabs["Web"] = "mimeType:text/html";
++            tabs["Text"] = "mimeType:text/*";
+         }
+         map<string, string>::const_iterator j;
+         string otherq = query;
+         for (j = tabs.begin(); j != tabs.end(); ++j) {
+-            string q = query+' '+j->second;
++            string q = query;
++            if (q != j->second) {
++                q += ' ' + j->second;
++            }
+             int c = p->strigi.countHits(q);
+             if (c > 0) {
+                 hitcounts[j->first] = c;
+                 doother &= c < count;
+-        otherq += " -" + j->second;
++                otherq += " -" + j->second;
+                 if (j->first == selectedtab || activetab.size() == 0) {
+                     activetab = j->first;
+                     activequery = q;
+@@ -424,9 +433,9 @@
+         icon = "<div class='iconbox'><img class='icon' src='"+icon;
+         icon += "'/></div>\n";
+     }
+-    t = doc.properties.find("audio.title");
++    t = doc.properties.find("title");
+     if (t == doc.properties.end()) {
+-        t = doc.properties.find("email.subject");
++        t = doc.properties.find("subject");
+     }
+     size_t l = doc.uri.rfind('/');
+     if (t != doc.properties.end()) {
+--- a/src/luceneindexer/cluceneindexmanager.cpp
++++ b/src/luceneindexer/cluceneindexmanager.cpp
+@@ -27,12 +27,17 @@
+ #include <CLucene.h>
+ #include "cluceneindexwriter.h"
+ #include "cluceneindexreader.h"
++#include "indexplugin.h"
+ #include <iostream>
+ #include <sys/types.h>
+ #include <time.h>
+ #include "timeofday.h"
+ #include "stgdirent.h" //our dirent compatibility header... uses native if available
+ 
++
++/* define and export the index factory */
++REGISTER_STRIGI_INDEXMANAGER(CLuceneIndexManager)
++
+ using namespace lucene::index;
+ using lucene::analysis::standard::StandardAnalyzer;
+ using lucene::store::FSDirectory;
+@@ -51,6 +56,11 @@
+     indexwriter = 0;
+     writer = new CLuceneIndexWriter(this);
+     analyzer = new StandardAnalyzer();
++    if (path == ":memory:") {
++        ramdirectory = new lucene::store::RAMDirectory();
++    } else {
++        ramdirectory = 0;
++    }
+     mtime = 0;
+ 
+     //remove any old segments lying around from crashes, etc
+@@ -67,6 +77,7 @@
+         r->second = 0;
+     }
+     closeWriter();
++    delete ramdirectory;
+     delete analyzer;
+     if (--numberOfManagers == 0) {
+ // temporarily commented out because of problem with clucene
+@@ -116,16 +127,22 @@
+ void
+ CLuceneIndexManager::openWriter(bool truncate) {
+     try {
+-        if (!truncate && IndexReader::indexExists(dbdir.c_str())) {
++        if (ramdirectory) {
++            indexwriter = new IndexWriter(ramdirectory, analyzer, true);
++        } else if (!truncate && IndexReader::indexExists(dbdir.c_str())) {
+             if (IndexReader::isLocked(dbdir.c_str())) {
+                 IndexReader::unlock(dbdir.c_str());
+             }
+             indexwriter = new IndexWriter(dbdir.c_str(), analyzer, false);
+         } else {
+-            indexwriter = new IndexWriter(dbdir.c_str(), analyzer, true, true);
++            indexwriter = new IndexWriter(dbdir.c_str(), analyzer, true);
+         }
+     } catch (CLuceneError& err) {
+-        printf("could not create writer: %s\n", err.what());
++        fprintf(stderr, "could not create writer: %s\n", err.what());
++        indexwriter = 0;
++    } catch (...) {
++        fprintf(stderr, "Unknown exception was thrown.");
++        indexwriter = 0;
+     }
+ }
+ void
+@@ -201,3 +218,4 @@
+     mtime = t.tv_sec;
+     lock.unlock();
+ }
++
+--- a/src/luceneindexer/cluceneindexmanager.h
++++ b/src/luceneindexer/cluceneindexmanager.h
+@@ -22,7 +22,6 @@
+ 
+ #include <strigi/strigiconfig.h>
+ #include "indexmanager.h"
+-//#include "querybitset.h"
+ #include <strigi_thread.h>
+ #include <string>
+ #include <map>
+@@ -38,6 +37,9 @@
+         class IndexWriter;
+         class IndexReader;
+     }
++    namespace store {
++        class RAMDirectory;
++    }
+ }
+ 
+ class CLuceneIndexReader;
+@@ -50,13 +52,14 @@
+     std::map<STRIGI_THREAD_TYPE, CLuceneIndexReader*> readers;
+     CLuceneIndexWriter* writer;
+     lucene::index::IndexWriter* indexwriter;
+-    //Strigi::QueryBitsetCache bitsets;
+     lucene::analysis::Analyzer* analyzer;
+     time_t mtime;
+     static int numberOfManagers;
+ 
+     void openWriter(bool truncate=false);
+ public:
++    lucene::store::RAMDirectory* ramdirectory;
++
+     explicit CLuceneIndexManager(const std::string& path);
+     ~CLuceneIndexManager();
+ 
+@@ -65,7 +68,6 @@
+     Strigi::IndexReader* indexReader();
+     Strigi::IndexWriter* indexWriter();
+     CLuceneIndexReader* luceneReader();
+-//    Strigi::QueryBitsetCache* bitSets();
+     int32_t docCount();
+     int64_t indexSize();
+     void deleteIndex();
+@@ -74,7 +76,4 @@
+     void setIndexMTime();
+ };
+ 
+-CLUCENEINDEXER_EXPORT Strigi::IndexManager*
+-createCLuceneIndexManager(const char* path);
+-
+ #endif
+--- a/src/luceneindexer/cluceneindexreader.cpp
++++ b/src/luceneindexer/cluceneindexreader.cpp
+@@ -137,7 +137,11 @@
+     doccount = -1;
+     wordcount = -1;
+     try {
+-        reader = lucene::index::IndexReader::open(dbdir.c_str());
++        if (manager->ramdirectory) {
++            reader = lucene::index::IndexReader::open(manager->ramdirectory);
++        } else {
++            reader = lucene::index::IndexReader::open(dbdir.c_str());
++        }
+         //fprintf(stderr,
+         //"reader at %s: %i\n", dbdir.c_str(), reader->numDocs());
+     } catch (CLuceneError& err) {
+@@ -585,14 +589,14 @@
+     vector<int32_t>::const_iterator i;
+     struct tm t;
+     for (i = v.begin(); i < v.end(); ++i) {
+-         time_t ti = *i;
++        time_t ti = *i;
+ #ifdef _WIN32
+         t = *localtime( &ti );   // is thread-safe on win32
+ #else
+-         localtime_r(&ti, &t);
++        localtime_r(&ti, &t);
+ #endif
+-         int32_t c = 10000*t.tm_year + 100*t.tm_mon + t.tm_mday;
+-         m[c]++;
++        int32_t c = 10000*t.tm_year + 100*t.tm_mon + t.tm_mday;
++        m[c]++;
+     }
+     vector<pair<string,uint32_t> > h;
+     h.reserve(m.size());
+--- a/src/luceneindexer/cluceneindexwriter.cpp
++++ b/src/luceneindexer/cluceneindexwriter.cpp
+@@ -240,8 +240,11 @@
+             if (t && _tcsncmp(t, prefixText, prefixLen) == 0) {
+                 try {
+                     reader->deleteDocument(i);
++                } catch (CLuceneError& err) {
++                    cerr << "Could not delete document '" << entry
++                        << "' from the index: " << err.what() << endl;
+                 } catch (...) {
+-                    fprintf(stderr, "could not delete document");
++                    cerr << "This should not happen." << endl;
+                 }
+             }
+             _CLDELETE(d);
+--- a/src/luceneindexer/CMakeLists.txt
++++ b/src/luceneindexer/CMakeLists.txt
+@@ -19,42 +19,44 @@
+     ADD_DEFINITIONS(-DUNICODE)
+ ENDIF(WIN32)
+ 
+-# CLucene requires exception support and has no support for visibility=hidden
+-# so we must use the default (i.e. public) value for -fvisibility
++# CLucene requires exception support
+ IF(NOT WIN32)
+     IF (CMAKE_COMPILER_IS_GNUCXX)
+         set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions")
+     ENDIF(CMAKE_COMPILER_IS_GNUCXX)
+ ENDIF(NOT WIN32)
+-IF(__STRIGI_HAVE_GCC_VISIBILITY)
+-    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=default")
+-ENDIF(__STRIGI_HAVE_GCC_VISIBILITY)
++# In the past, we though we needed to use -fvisibility=default for compiling
++# this library. This appears not to be the case anymore.
++#IF(__STRIGI_HAVE_GCC_VISIBILITY)
++#    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=default")
++#ENDIF(__STRIGI_HAVE_GCC_VISIBILITY)
+ 
+ set(cluceneindex_SRCS
+-#        PrefixFilter.cpp
+-        cluceneindexmanager.cpp
+-        cluceneindexreader.cpp
+-        cluceneindexwriter.cpp
+-        jsgzipcompressstream.cpp
+-	tcharutils.cpp
++    cluceneindexmanager.cpp
++    cluceneindexreader.cpp
++    cluceneindexwriter.cpp
++    jsgzipcompressstream.cpp
++    tcharutils.cpp
+ )
+ 
+-add_library(cluceneindex SHARED ${cluceneindex_SRCS})
+-
+-set_target_properties(cluceneindex
+-    PROPERTIES VERSION ${STRIGI_VERSION}
+-    SOVERSION ${STRIGI_VERSION_MAJOR}
+-    DEFINE_SYMBOL MAKE_CLUCENEINDEXER_LIB
+-)
+-
+-target_link_libraries(cluceneindex streamanalyzer ${CLUCENE_LIBRARY})
++if(WIN32)
++  # this is needed to have mingw, cygwin and msvc libs installed in one directory
++  if(MSVC)
++    set(prefix msvc_strigiindex_)
++  elseif(CYGWIN)
++    set(prefix cyg_strigiindex_)
++  elseif(MINGW)
++    set(prefix mingw_strigiindex_)
++  endif(MSVC)
++else(WIN32)
++  set(prefix strigiindex_)
++endif(WIN32)
++add_library(clucene MODULE ${cluceneindex_SRCS})
++set_target_properties(clucene PROPERTIES PREFIX ${prefix})
++target_link_libraries(clucene ${CLUCENE_LIBRARY})
++install(TARGETS clucene LIBRARY DESTINATION ${LIB_DESTINATION}/strigi)
+ 
+ add_executable(luceneindexer luceneindexer.cpp)
+-target_link_libraries(luceneindexer cluceneindex)
++target_link_libraries(luceneindexer streamanalyzer)
+ 
+ install(TARGETS luceneindexer RUNTIME DESTINATION bin)
+-install(TARGETS cluceneindex
+-	LIBRARY DESTINATION ${LIB_DESTINATION}
+-	RUNTIME DESTINATION bin
+-	ARCHIVE DESTINATION  ${LIB_DESTINATION}
+-)
+--- a/src/luceneindexer/indexdump/CMakeLists.txt
++++ b/src/luceneindexer/indexdump/CMakeLists.txt
+@@ -1,4 +1,4 @@
+ include_directories(${CLUCENE_LIBRARY_DIR} ${CLUCENE_INCLUDE_DIR}
+ 	${ICONV_INCLUDE_DIR} ..)
+-add_executable(indexdump indexdump.cpp)
+-target_link_libraries(indexdump ${CLUCENE_LIBRARY} cluceneindex)
++add_executable(indexdump indexdump.cpp ../tcharutils.cpp)
++target_link_libraries(indexdump streamanalyzer ${CLUCENE_LIBRARY})
+--- a/src/luceneindexer/luceneindexer.cpp
++++ b/src/luceneindexer/luceneindexer.cpp
+@@ -18,9 +18,8 @@
+  * Boston, MA 02110-1301, USA.
+  */
+ #include <strigi/strigiconfig.h>
+-#include <CLucene.h>
+ #include "diranalyzer.h"
+-#include "cluceneindexmanager.h"
++#include "indexpluginloader.h"
+ #include "analyzerconfiguration.h"
+ #include <iostream>
+ #include <sys/types.h>
+@@ -65,10 +64,13 @@
+     Strigi::AnalyzerConfiguration ic;
+     ic.setFilters(filters);
+     try {
+-        Strigi::IndexManager *manager = createCLuceneIndexManager(argv[1]);
+-        Strigi::DirAnalyzer analyzer(*manager, ic);
+-        analyzer.analyzeDir(argv[2]);
+-        delete manager;
++        Strigi::IndexManager *manager
++            = Strigi::IndexPluginLoader::createIndexManager("clucene", argv[1]);
++        if (manager) {
++            Strigi::DirAnalyzer analyzer(*manager, ic);
++            analyzer.analyzeDir(argv[2]);
++            Strigi::IndexPluginLoader::deleteIndexManager(manager);
++        }
+     } catch (...) {
+         cerr << "error while creating index" << endl;
+     }
+--- a/src/luceneindexer/tcharutils.h
++++ b/src/luceneindexer/tcharutils.h
+@@ -25,9 +25,9 @@
+ #include <string>
+ #include <strigi/strigiconfig.h>
+ 
+-std::string CLUCENEINDEXER_EXPORT wchartoutf8(const wchar_t*);
+-std::wstring CLUCENEINDEXER_EXPORT utf8toucs2(const char*);
+-std::string CLUCENEINDEXER_EXPORT wchartoutf8(const std::wstring&);
+-std::wstring CLUCENEINDEXER_EXPORT utf8toucs2(const std::string&);
++std::string wchartoutf8(const wchar_t*);
++std::wstring utf8toucs2(const char*);
++std::string wchartoutf8(const std::wstring&);
++std::wstring utf8toucs2(const std::string&);
+ 
+ #endif
+--- a/src/luceneindexer/tests/CLuceneTest.cpp
++++ b/src/luceneindexer/tests/CLuceneTest.cpp
+@@ -1,5 +1,6 @@
+ #include <strigi/strigiconfig.h>
+-#include "cluceneindexmanager.h"
++#include "indexpluginloader.h"
++#include "indexmanager.h"
+ #include "indexmanagertests.h"
+ #include "indexwritertests.h"
+ #include "indexreadertests.h"
+@@ -23,7 +24,12 @@
+ #else
+     mkdir(path, S_IRUSR|S_IWUSR|S_IXUSR);
+ #endif
+-    Strigi::IndexManager* manager = createCLuceneIndexManager(path);
++    Strigi::IndexManager* manager
++        = Strigi::IndexPluginLoader::createIndexManager("clucene", path);
++    if (manager == 0) {
++        founderrors++;
++        return founderrors;
++    }
+ 
+     Strigi::AnalyzerConfiguration ic;
+     IndexManagerTests tests(manager, ic);
+@@ -39,7 +45,7 @@
+     rtests.testAll();
+ 
+     // close and clean up the manager
+-    delete manager;
++    Strigi::IndexPluginLoader::deleteIndexManager(manager);
+ 
+     // clean up data
+     std::string cmd = "rm -r ";
+--- a/src/luceneindexer/tests/CMakeLists.txt
++++ b/src/luceneindexer/tests/CMakeLists.txt
+@@ -3,7 +3,7 @@
+ CREATE_TEST_SOURCELIST(Tests testrunner.cpp CLuceneTest.cpp)
+ 
+ ADD_EXECUTABLE(testrunner-lucene ${Tests} )
+-target_link_libraries(testrunner-lucene streams cluceneindex indexertests)
++target_link_libraries(testrunner-lucene streamanalyzer indexertests)
+ 
+ SET (TestsToRun ${Tests})
+ REMOVE (TestsToRun testrunner.cpp)
+--- a/src/sqliteindexer/CMakeLists.txt
++++ b/src/sqliteindexer/CMakeLists.txt
+@@ -4,14 +4,23 @@
+ 	${SQLITE_LIBRARY_DIR} ${SQLITE_INCLUDE_DIR}
+ 	${strigi_BINARY_DIR}/src/streams)
+ 
+-add_library(sqliteindex
++if(WIN32)
++  # this is needed to have mingw, cygwin and msvc libs installed in one directory
++  if(MSVC)
++    set(prefix msvc_strigiindex_)
++  elseif(CYGWIN)
++    set(prefix cyg_strigiindex_)
++  elseif(MINGW)
++    set(prefix mingw_strigiindex_)
++  endif(MSVC)
++else(WIN32)
++  set(prefix strigiindex_)
++endif(WIN32)
++add_library(sqlite MODULE
+ 	sqliteindexmanager.cpp
+         sqliteindexreader.cpp
+ 	sqliteindexwriter.cpp
+ )
+-
+-target_link_libraries(sqliteindex streamanalyzer ${SQLITE_LIBRARIES})
+-
+-add_executable(sqliteindexer sqliteindexer.cpp)
+-target_link_libraries(sqliteindexer sqliteindex sqlite3)
+-
++set_target_properties(sqlite PROPERTIES PREFIX ${prefix})
++target_link_libraries(sqlite ${SQLITE_LIBRARIES})
++install(TARGETS sqlite LIBRARY DESTINATION ${LIB_DESTINATION}/strigi)
+--- a/src/sqliteindexer/sqliteindexmanager.cpp
++++ b/src/sqliteindexer/sqliteindexmanager.cpp
+@@ -21,15 +21,15 @@
+ #include "sqliteindexreader.h"
+ #include "sqliteindexwriter.h"
+ #include "strigi_thread.h"
++#include "indexplugin.h"
++#include <iostream>
+ using namespace std;
+ using namespace Strigi;
+ 
+-pthread_mutex_t SqliteIndexManager::lock = PTHREAD_MUTEX_INITIALIZER;
++/* define and export the index factory */
++REGISTER_STRIGI_INDEXMANAGER(SqliteIndexManager)
+ 
+-Strigi::IndexManager*
+-createSqliteIndexManager(const char* path) {
+-    return new SqliteIndexManager(path);
+-}
++pthread_mutex_t SqliteIndexManager::lock = PTHREAD_MUTEX_INITIALIZER;
+ 
+ SqliteIndexManager::SqliteIndexManager(const char* dbfile) {
+     dblock = lock;
+@@ -51,6 +51,7 @@
+ }
+ sqlite3*
+ SqliteIndexManager::opendb(const char* path) {
++    // check if the database already exists
+     sqlite3* db;
+     int r = sqlite3_open(path, &db);
+     // any value other than SQLITE_OK is an error
+@@ -85,9 +86,8 @@
+ ;
+     r = sqlite3_exec(db, sql, 0, 0, 0);
+     if (r != SQLITE_OK) {
+-        fprintf(stderr, "could not create table %i %s\n", r,
+-            sqlite3_errmsg(db));
+-        exit(1);
++        //fprintf(stderr, "could not create table %i %s.\n", r,
++        //    sqlite3_errmsg(db));
+     }
+ 
+     // create temporary tables
+--- a/src/sqliteindexer/sqliteindexmanager.h
++++ b/src/sqliteindexer/sqliteindexmanager.h
+@@ -54,7 +54,5 @@
+     static std::string escapeSqlValue(const std::string& value);
+     static sqlite3* opendb(const char*);
+ };
+-Strigi::IndexManager*
+-createSqliteIndexManager(const char* path);
+ 
+ #endif
+--- a/src/sqliteindexer/sqliteindexreader.cpp
++++ b/src/sqliteindexer/sqliteindexreader.cpp
+@@ -20,6 +20,7 @@
+ #include "sqliteindexreader.h"
+ #include "sqliteindexmanager.h"
+ #include <set>
++#include <iostream>
+ #include <sstream>
+ using namespace std;
+ using namespace Strigi;
+@@ -61,7 +62,7 @@
+         q << "f"<<a<<".count*1.0/w"<<a<<".count";
+     }
+     if (n > 0) {
+-    q <<") p ";
++        q <<") p ";
+     }
+     q <<" from ";
+     for (int i=0; i<n; ++i) {
+@@ -93,16 +94,55 @@
+ 
+     return q.str();
+ }
++string
++createQuery(const Query& query, int off, int max) {
++    // TODO: makeing a query with wildcards slows things down, so we must
++    // think about reordering them
++    // although we'll never be able to manage queries like 'a% b% c%'
++    ostringstream q;
++    q << "select path from ";
++    //
++    for (int i=0; i<n; ++i) {
++        q << "words w" << i << ",";
++    }
++    for (int i=0; i<n; ++i) {
++        q << "filewords f" << i << ",";
++    }
++    q <<"files where ";
++    for (int i=0; i<n; ++i) {
++        q << "w" << i << ".word like ? and w" << i << ".wordid = f" << i
++            << ".wordid and ";
++    }
++    for (int i=1; i<n; ++i) {
++        q << "f0.fileid = f" << i << ".fileid and ";
++    }
++    if (n > 0) {
++        q <<"f0.fileid = files.fileid ";
++    }
++    if (filterpath) {
++        if (n > 0) q <<"and ";
++        q <<"files.path like ? ";
++    }
++    if (n > 0) q <<"group by fa.fileid order by p ";
++    q << "limit " << max << " offset " << off;
++
++    return q.str();
++}
+ int
+ SqliteIndexReader::countHits(const Strigi::Query& q) {
+     // very inefficient: needs refactoring
+     vector<IndexedDocument> r = query(q, 0, 1000000);
+     return r.size();
+ }
++string
++createQuery(const Query& query) {
++    return "select path from files;";
++}
+ vector<IndexedDocument>
+ SqliteIndexReader::query(const Strigi::Query& query, int off, int max) {
+-    string q;
+-    // replace * by %
++    string sql(createQuery(query, off, max));
++    vector<IndexedDocument> results;
++/*    // replace * by %
+     size_t p = q.find('*');
+     while (p != string::npos) {
+         q.replace(p, 1, "%");
+@@ -116,7 +156,6 @@
+     }
+     // split up in terms
+     set<string> terms = split(q);
+-    vector<IndexedDocument> results;
+     if (terms.size() == 0) return results;
+     string pathfilter;
+     set<string>::iterator i = terms.begin();
+@@ -132,17 +171,17 @@
+     if (terms.size() == 0 && pathfilter.length() == 0) return results;
+ 
+     string sql = createQuery(terms.size(), pathfilter.length() > 0);
+-
++*/
+     sqlite3* db = manager->ref();
+     sqlite3_stmt* stmt;
+     int r = sqlite3_prepare(db, sql.c_str(), -1, &stmt, 0);
+     if (r != SQLITE_OK) {
+-        printf("could not prepare query '%s': %s\n", sql.c_str(),
++        fprintf(stderr, "could not prepare query '%s': %s\n", sql.c_str(),
+             sqlite3_errmsg(db));
+         manager->deref();
+         return results;
+     }
+-    int j = 1;
++/*    int j = 1;
+     for (i=terms.begin(); i!=terms.end(); ++i) {
+         sqlite3_bind_text(stmt, j++, i->c_str(), i->length(),
+             SQLITE_STATIC);
+@@ -150,7 +189,7 @@
+     if (pathfilter.length() > 0) {
+         sqlite3_bind_text(stmt, j, pathfilter.c_str(), pathfilter.length(),
+             SQLITE_STATIC);
+-    }
++    }*/
+     r = sqlite3_step(stmt);
+     while (r == SQLITE_ROW) {
+         IndexedDocument doc;
+@@ -245,3 +284,10 @@
+     vector<string> k;
+     return k;
+ }
++void
++SqliteIndexReader::getHits(const Strigi::Query& query,
++        const std::vector<std::string>& fields,
++        const std::vector<Strigi::Variant::Type>& types,
++        std::vector<std::vector<Strigi::Variant> >& result,
++        int off, int max) {
++}
+--- a/src/sqliteindexer/sqliteindexreader.h
++++ b/src/sqliteindexer/sqliteindexreader.h
+@@ -48,6 +48,11 @@
+     std::vector<std::string> keywords(const std::string& keywordmatch,
+         const std::vector<std::string>& fieldnames,
+         uint32_t max, uint32_t offset);
++    void getHits(const Strigi::Query& query,
++        const std::vector<std::string>& fields,
++        const std::vector<Strigi::Variant::Type>& types,
++        std::vector<std::vector<Strigi::Variant> >& result,
++        int off, int max);
+ };
+ 
+ #endif
+--- a/src/sqliteindexer/sqliteindexwriter.cpp
++++ b/src/sqliteindexer/sqliteindexwriter.cpp
+@@ -183,6 +183,7 @@
+         = content.find(wdata->id);
+ 
+     if (m == content.end()) {
++        delete wdata;
+         return;
+     }
+ 
+@@ -199,6 +200,7 @@
+             sqlite3_errmsg(db));
+         content.erase(m->first);
+         manager->deref();
++        delete wdata;
+         return;
+     }
+     map<string, int>::const_iterator i = m->second.begin();
+@@ -209,7 +211,7 @@
+             SQLITE_STATIC);
+         sqlite3_bind_int(stmt, 3, i->second);
+         r = sqlite3_step(stmt);
+-        if (r != 21) { // what is 21?
++        if (r != SQLITE_DONE) { // what is 21?
+             fprintf(stderr, "could not write content into database: %i %s\n", r,
+                 sqlite3_errmsg(db));
+         }
+--- a/src/sqliteindexer/tests/CMakeLists.txt
++++ b/src/sqliteindexer/tests/CMakeLists.txt
+@@ -3,7 +3,7 @@
+ CREATE_TEST_SOURCELIST(Tests testrunner.cpp SqliteTest.cpp simpletest.cpp)
+ 
+ ADD_EXECUTABLE(sqlitetest ${Tests} )
+-target_link_libraries(sqlitetest streams sqliteindex indexertests)
++target_link_libraries(sqlitetest streams indexertests)
+ 
+ SET (TestsToRun ${Tests})
+ REMOVE (TestsToRun testrunner.cpp)
+--- a/src/sqliteindexer/tests/simpletest.cpp
++++ b/src/sqliteindexer/tests/simpletest.cpp
+@@ -1,5 +1,6 @@
+ #include <strigi/strigiconfig.h>
+-#include "sqliteindexmanager.h"
++#include "indexpluginloader.h"
++#include "indexmanager.h"
+ #include "indexwriter.h"
+ #include "indexreader.h"
+ #include "analyzerconfiguration.h"
+@@ -38,13 +39,14 @@
+     mkdir(path, S_IRUSR|S_IWUSR|S_IXUSR);
+     string p(path);
+     p += "/test.db";
+-    IndexManager* manager = createSqliteIndexManager(p.c_str());
++    Strigi::IndexManager* manager
++        = Strigi::IndexPluginLoader::createIndexManager("sqlite", p.c_str());
+     IndexWriter* writer = manager->indexWriter();
+     IndexReader* reader = manager->indexReader();
+     addAndCount(writer, reader, 1);
+ 
+     // close and clean up the manager
+-    delete manager;
++    Strigi::IndexPluginLoader::deleteIndexManager(manager);
+ 
+     // clean up data
+ /*    std::string cmd = "rm -r ";
+--- a/src/sqliteindexer/tests/SqliteTest.cpp
++++ b/src/sqliteindexer/tests/SqliteTest.cpp
+@@ -1,5 +1,5 @@
+ #include <strigi/strigiconfig.h>
+-#include "sqliteindexmanager.h"
++#include "indexpluginloader.h"
+ #include "indexmanagertests.h"
+ #include "indexwritertests.h"
+ #include "indexreadertests.h"
+@@ -18,7 +18,8 @@
+     mkdir(path, S_IRUSR|S_IWUSR|S_IXUSR);
+     string p(path);
+     p += "/test.db";
+-    Strigi::IndexManager* manager = createSqliteIndexManager(p.c_str());
++    Strigi::IndexManager* manager
++        = Strigi::IndexPluginLoader::createIndexManager("sqlite", p.c_str());
+ 
+     Strigi::AnalyzerConfiguration ic;
+     IndexManagerTests tests(manager, ic);
+@@ -34,7 +35,7 @@
+     rtests.testAll();
+ */
+     // close and clean up the manager
+-    delete manager;
++    Strigi::IndexPluginLoader::deleteIndexManager(manager);
+ 
+     // clean up data
+     std::string cmd = "rm -r ";
+--- a/src/streamanalyzer/classproperties.cpp
++++ b/src/streamanalyzer/classproperties.cpp
+@@ -25,7 +25,6 @@
+ using namespace Strigi;
+ using namespace std;
+ 
+-const string ClassProperties::Private::empty;
+ ClassProperties::ClassProperties() :p(new Private()) {
+ }
+ ClassProperties::ClassProperties(const Private& pr) :p(new Private(pr)) {}
+@@ -70,12 +69,12 @@
+ const string&
+ ClassProperties::localizedName(const string& locale) const {
+     map<string,Localized>::iterator i = p->localized.find(locale);
+-    return (i == p->localized.end()) ?Private::empty :i->second.name;
++    return (i == p->localized.end()) ?empty() :i->second.name;
+ }
+ const string&
+ ClassProperties::localizedDescription(const string& locale) const {
+     map<string,Localized>::iterator i = p->localized.find(locale);
+-    return (i == p->localized.end()) ?Private::empty :i->second.description;
++    return (i == p->localized.end()) ?empty() :i->second.description;
+ }
+ const vector<string>&
+ ClassProperties::parentUris() const {
+--- a/src/streamanalyzer/CMakeLists.txt
++++ b/src/streamanalyzer/CMakeLists.txt
+@@ -26,6 +26,7 @@
+ 	htmlsaxanalyzer.cpp
+ 	id3v2throughanalyzer.cpp
+         indexreader.cpp
++	indexpluginloader.cpp
+ 	lineeventanalyzer.cpp
+ 	m3ustreamanalyzer.cpp
+ 	mimeeventanalyzer.cpp
+@@ -97,6 +98,9 @@
+ 	fieldproperties.h
+ 	fieldtypes.h
+ 	indexeddocument.h
++	indexreader.h
++	indexmanager.h
++	indexplugin.h
+ 	indexwriter.h
+ 	streamanalyzer.h
+ 	streamanalyzerfactory.h
+--- a/src/streamanalyzer/fieldproperties.cpp
++++ b/src/streamanalyzer/fieldproperties.cpp
+@@ -25,7 +25,6 @@
+ using namespace Strigi;
+ using namespace std;
+ 
+-const string FieldProperties::Private::empty;
+ FieldProperties::FieldProperties() :p(new Private()) {
+ }
+ FieldProperties::FieldProperties(const Private& pr) :p(new Private(pr)) {}
+@@ -102,12 +101,12 @@
+ const string&
+ FieldProperties::localizedName(const string& locale) const {
+     map<string,Localized>::iterator i = p->localized.find(locale);
+-    return (i == p->localized.end()) ?Private::empty :i->second.name;
++    return (i == p->localized.end()) ?empty() :i->second.name;
+ }
+ const string&
+ FieldProperties::localizedDescription(const string& locale) const {
+     map<string,Localized>::iterator i = p->localized.find(locale);
+-    return (i == p->localized.end()) ?Private::empty :i->second.description;
++    return (i == p->localized.end()) ?empty() :i->second.description;
+ }
+ const vector<string>&
+ FieldProperties::parentUris() const {
+--- a/src/streamanalyzer/fieldpropertiesdb.cpp
++++ b/src/streamanalyzer/fieldpropertiesdb.cpp
+@@ -39,7 +39,8 @@
+ #include <map>
+ #include <iostream>
+ #include <list>
+-#include <string>
++#include <set>
++
+ using namespace Strigi;
+ using namespace std;
+ 
+@@ -47,8 +48,8 @@
+ public:
+     map<string, FieldProperties> properties;
+     map<string, ClassProperties> classes;
+-    static FieldProperties emptyField;
+-    static ClassProperties emptyClass;
++    static const FieldProperties& emptyField();
++    static const ClassProperties& emptyClass();
+ 
+     Private();
+     static vector<string> getdirs(const string&);
+@@ -94,8 +95,16 @@
+ 
+ };
+ 
+-FieldProperties FieldPropertiesDb::Private::emptyField;
+-ClassProperties FieldPropertiesDb::Private::emptyClass;
++const FieldProperties&
++FieldPropertiesDb::Private::emptyField() {
++    static const FieldProperties e;
++    return e;
++}
++const ClassProperties&
++FieldPropertiesDb::Private::emptyClass() {
++    static const ClassProperties f;
++    return f;
++}
+ 
+ FieldPropertiesDb&
+ FieldPropertiesDb::db() {
+@@ -112,7 +121,7 @@
+     map<std::string, FieldProperties>::const_iterator j
+         = p->properties.find(uri);
+     if (j == p->properties.end()) {
+-        return FieldPropertiesDb::Private::emptyField;
++        return FieldPropertiesDb::Private::emptyField();
+     } else {
+         return j->second;
+     }
+@@ -126,7 +135,7 @@
+ FieldPropertiesDb::classes(const std::string& uri) const {
+     map<std::string, ClassProperties>::const_iterator j = p->classes.find(uri);
+     if (j == p->classes.end()) {
+-        return FieldPropertiesDb::Private::emptyClass;
++        return FieldPropertiesDb::Private::emptyClass();
+     } else {
+         return j->second;
+     }
+@@ -178,8 +187,12 @@
+ 
+     vector<string> dirs = getXdgDirs();
+     vector<string>::const_iterator i;
++    set<string> done;
+     for (i=dirs.begin(); i!=dirs.end(); i++) {
+-        loadProperties(*i);
++        if (done.find(*i) == done.end()) {
++            done.insert(*i);
++            loadProperties(*i);
++        }
+     }
+ 
+     // Generate childUris, applicable* and locales values.
+@@ -255,6 +268,9 @@
+     props.uri = FieldRegister::filenameFieldName;
+     properties[FieldRegister::filenameFieldName] = props;
+ 
++    props.uri = FieldRegister::mimetypeFieldName;
++    properties[FieldRegister::mimetypeFieldName] = props;
++
+     props.uri = FieldRegister::parentLocationFieldName;
+     props.tokenized = false;
+     properties[FieldRegister::parentLocationFieldName] = props;
+@@ -263,13 +279,23 @@
+ FieldPropertiesDb::Private::loadProperties(const string& dir) {
+     string pdir = dir + "/strigi/fieldproperties/";
+     DIR* d = opendir(pdir.c_str());
+-    if (!d) return;
++    if (!d) {
++        pdir = dir;
++        d = opendir(pdir.c_str());
++    }
++    if (!d) {
++        return;
++    }
++    if (pdir[pdir.length()-1] != '/') {
++        pdir.append("/");
++    }
+     struct dirent* de = readdir(d);
+     struct stat s;
+     char* data = 0;
+     while (de) {
+         string path(pdir+de->d_name);
+-        if (!stat(path.c_str(), &s) && S_ISREG(s.st_mode)) {
++        if (path.length() >= 5 && path.substr(path.length()-5) == ".rdfs" &&
++                !stat(path.c_str(), &s) && S_ISREG(s.st_mode)) {
+             FILE* f = fopen(path.c_str(), "r");
+             if (f) {
+                 // read the entire file at once
+--- a/src/streamanalyzer/fieldproperties_private.h
++++ b/src/streamanalyzer/fieldproperties_private.h
+@@ -24,12 +24,18 @@
+ #include "fieldproperties.h"
+ #include "fieldtypes.h"
+ 
++namespace {
++    const std::string& empty() {
++        static std::string e;
++        return e;
++    }
++}
++
+ namespace Strigi {
+ 
+ class FieldProperties::Private {
+ friend class FieldPropertiesDb;
+ public:
+-    static const std::string empty;
+     std::string uri;
+     std::string name;
+     std::string typeuri;
+@@ -69,7 +75,6 @@
+ class ClassProperties::Private {
+ friend class FieldPropertiesDb;
+ public:
+-    static const std::string empty;
+     std::string uri;
+     std::string name;
+     std::string description;
+--- a/src/streamanalyzer/fieldtypes.cpp
++++ b/src/streamanalyzer/fieldtypes.cpp
+@@ -103,7 +103,7 @@
+             = FieldPropertiesDb::db().properties(fieldname);
+         if (!props.valid()) {
+             cerr << "WARNING: field '" << fieldname << "' is not defined in "
+-                ".fieldproperties ontology database." << endl;
++                "any rdfs ontology database." << endl;
+ 	    // creates a field with defaults (stringType and no parents)
+             FieldPropertiesDb::db().addField(fieldname);
+         }
+--- a/src/streamanalyzer/filelister.cpp
++++ b/src/streamanalyzer/filelister.cpp
+@@ -47,34 +47,37 @@
+ using namespace std;
+ using namespace Strigi;
+ 
+-/*!
+-* @param path string containing path to check
+-* Appends the terminating char to path.
+-* Under Windows that char is '\', '/' under *nix
+-*/
+-string fixPath (string path)
++namespace
+ {
+-    if ( path.c_str() == NULL || path.length() == 0 )
+-        return "";
+-
+-    string temp(path);
+-
+-#ifdef HAVE_WINDOWS_H
+-    size_t l= temp.length();
+-    char* t = (char*)temp.c_str();
+-    for (size_t i=0;i<l;i++){
+-        if ( t[i] == '\\' )
+-            t[i] = '/';
+-    }
+-    temp[0] = tolower(temp.at(0));
+-#endif
++    /*!
++    * @param path string containing path to check
++    * Appends the terminating char to path.
++    * Under Windows that char is '\', '/' under *nix
++    */
++    string fixPath (string path)
++    {
++        if ( path.c_str() == NULL || path.length() == 0 )
++            return "";
++
++        string temp(path);
++
++    #ifdef HAVE_WINDOWS_H
++        size_t l= temp.length();
++        char* t = (char*)temp.c_str();
++        for (size_t i=0;i<l;i++){
++            if ( t[i] == '\\' )
++                t[i] = '/';
++        }
++        temp[0] = tolower(temp.at(0));
++    #endif
+ 
+-    char separator = '/';
++        char separator = '/';
+ 
+-    if (temp[temp.length() - 1 ] != separator)
+-        temp += separator;
++        if (temp[temp.length() - 1 ] != separator)
++            temp += separator;
+ 
+-    return temp;
++        return temp;
++    }
+ }
+ 
+ class FileLister::Private {
+--- a/src/streamanalyzer/filelister.h
++++ b/src/streamanalyzer/filelister.h
+@@ -45,7 +45,6 @@
+ 
+ namespace Strigi {
+ 
+-
+ class FileLister {
+ private:
+     class Private;
+@@ -72,7 +71,7 @@
+     void skipTillAfter(const std::string& lastToSkip);
+ };
+ 
+-class DirLister {
++class STRIGI_EXPORT DirLister {
+ private:
+     class Private;
+     Private* p;
+--- a/src/streamanalyzer/indexmanager.h
++++ b/src/streamanalyzer/indexmanager.h
+@@ -24,6 +24,9 @@
+ class IndexReader;
+ class IndexWriter;
+ 
++class IndexManager;
++void deleteIndexManager(Strigi::IndexManager* m);
++
+ /**
+  * Abstract interface that manages access to the IndexReader and IndexWriter
+  * instances provided by a particular index backend.
+@@ -38,6 +41,7 @@
+  * be used in the active thread.
+  **/
+ class IndexManager {
++friend void deleteIndexManager(Strigi::IndexManager* m);
+ public:
+     virtual ~IndexManager() {}
+     /**
+--- /dev/null
++++ b/src/streamanalyzer/indexplugin.h
+@@ -0,0 +1,40 @@
++/* This file is part of Strigi Desktop Search
++ *
++ * Copyright (C) 2007 Jos van den Oever <jos at vandenoever.info>
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public License
++ * along with this library; see the file COPYING.LIB.  If not, write to
++ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
++ * Boston, MA 02110-1301, USA.
++ */
++
++#ifndef STRIGI_INDEXPLUGIN_H
++#define STRIGI_INDEXPLUGIN_H
++#include <strigi/strigiconfig.h>
++
++/**
++ * @brief Macro to register functions for creating and deleting an indexmanager
++ *        in a plugin
++ *
++ * @param CLASS the name of the subclass of Strigi::IndexManager
++ */
++#define REGISTER_STRIGI_INDEXMANAGER(CLASS) extern "C" { \
++    STRIGI_EXPORT Strigi::IndexManager* createIndexManager(const char* dir) { \
++        return new CLASS(dir); \
++    } \
++    STRIGI_EXPORT void deleteIndexManager(Strigi::IndexManager* m) { \
++        delete m; \
++    } \
++}
++#endif
++
+--- /dev/null
++++ b/src/streamanalyzer/indexpluginloader.cpp
+@@ -0,0 +1,245 @@
++/* This file is part of Strigi Desktop Search
++ *
++ * Copyright (C) 2007 Jos van den Oever <jos at vandenoever.info>
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public License
++ * along with this library; see the file COPYING.LIB.  If not, write to
++ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
++ * Boston, MA 02110-1301, USA.
++ */
++#include "indexpluginloader.h"
++#include "indexmanager.h"
++#include <iostream>
++#include <stgdirent.h>
++#include <sys/stat.h>
++using namespace std;
++using namespace Strigi;
++
++#ifndef _WIN32
++#include <dlfcn.h>
++#define DLSYM dlsym
++#define DLCLOSE dlclose
++#else
++#define DLSYM GetProcAddress
++#define DLCLOSE FreeLibrary
++#endif
++
++#ifndef _WIN32
++typedef void* StgModuleType;
++#else
++#include <windows.h>
++typedef HMODULE StgModuleType;
++#endif
++
++// anonymous namespace for static variables
++namespace {
++    class Module {
++    private:
++        const StgModuleType mod;
++        Module(const Module&);
++        void operator=(const Module&);
++    public:
++        Strigi::IndexManager* (*create)(const char*);
++        void (*destroy)(Strigi::IndexManager*);
++        Module(StgModuleType m)
++            :mod(m) {}
++        ~Module() {
++// TODO: figure out why we get segfaults when cleaning up nicely
++            DLCLOSE(mod);
++        }
++    };
++    vector<string>
++    getdirs(const string& direnv) {
++        vector<string> dirs;
++        string::size_type lastp = 0;
++        string::size_type p = direnv.find(':');
++        while (p != string::npos) {
++            dirs.push_back(direnv.substr(lastp, p-lastp));
++            lastp = p+1;
++            p = direnv.find(':', lastp);
++        }
++        dirs.push_back(direnv.substr(lastp));
++        return dirs;
++    }
++    class ModuleList {
++    private:
++        map<std::string, Module*> modules;
++    public:
++        map<std::string, Module*>& mods() {
++            if (!initialized) initialize();
++            return modules;
++        };
++        map<void*, Module*> indexmanagers;
++        bool initialized;
++
++        ModuleList() {
++            initialized = false;
++        }
++        void initialize() {
++            initialized = true;
++            // load the plugins from the environment setting
++            string strigipluginpath;
++            if (getenv("STRIGI_PLUGIN_PATH")) {
++                strigipluginpath = getenv("STRIGI_PLUGIN_PATH");
++            }
++            vector<string> strigipluginpaths = getdirs(strigipluginpath);
++            if (strigipluginpath.size()) {
++                for (uint i=0; i<strigipluginpaths.size(); ++i) {
++                    IndexPluginLoader::loadPlugins(strigipluginpaths[i].c_str());
++                }
++            } else {
++                IndexPluginLoader::loadPlugins( LIBINSTALLDIR "/strigi");
++            }
++        }
++        ~ModuleList() {
++            // delete all leftover indexmanagers
++            // if code deletes the indexmanager on it's own, the error will
++            // appear here
++            map<void*, Module*>::iterator j;
++            for (j = indexmanagers.begin(); j != indexmanagers.end(); ++j) {
++                j->second->destroy(static_cast<IndexManager*>(j->first));
++            }
++            // unload all the modules
++            map<string, Module*>::iterator i;
++            for (i = modules.begin(); i != modules.end(); ++i) {
++                delete i->second;
++            }
++        }
++        void loadModule(const string& name, const string& dir);
++    };
++    void
++    ModuleList::loadModule(const string& name, const string& lib) {
++        // check if this module was already loaded
++        map<string, Module*>::iterator i = modules.find(name);
++        if (i != modules.end()) {
++            return;
++        }
++        StgModuleType handle;
++#ifdef HAVE_DLFCN_H
++        // do not use RTLD_GLOBAL here
++        // note: If neither RTLD_GLOBAL nor RTLD_LOCAL are specified,
++        // the default is RTLD_LOCAL.
++        handle = dlopen(lib.c_str(), RTLD_LAZY);
++#else
++        handle = LoadLibrary(lib.c_str());
++#endif
++        if (!handle) {
++#ifdef HAVE_DLFCN_H
++            cerr << "Could not load '" << lib << "':" << dlerror() << endl;
++#else
++            cerr << "Could not load '" << lib << "': GetLastError(): "
++                << GetLastError() << endl;
++#endif
++            return;
++        }
++        IndexManager*(*create)(const char*) = (IndexManager*(*)(const char*))
++            DLSYM(handle, "createIndexManager");
++        if (!create) {
++#ifndef WIN32
++            fprintf(stderr, "%s\n", dlerror());
++#else
++            fprintf(stderr, "GetLastError: %d\n", GetLastError());
++#endif
++            DLCLOSE(handle);
++            return;
++        }
++        void(*destroy)(IndexManager*) = (void(*)(IndexManager*))
++            DLSYM(handle, "deleteIndexManager");
++        if (!destroy) {
++#ifndef WIN32
++            fprintf(stderr, "%s\n", dlerror());
++#else
++            fprintf(stderr, "GetLastError: %d\n", GetLastError());
++#endif
++            DLCLOSE(handle);
++            return;
++        }
++        Module* module = new Module(handle);
++        module->create = create;
++        module->destroy = destroy;
++        modules[name] = module;
++    }
++    static ModuleList modules;
++}
++void
++IndexPluginLoader::loadPlugins(const char* d) {
++    DIR *dir = opendir(d);
++    if (dir == 0) {
++        return;
++    }
++    struct dirent* ent = readdir(dir);
++    string prefix("strigiindex_");
++#ifdef WIN32
++    string suffix(".dll");
++#else
++    string suffix(".so");
++#endif
++    while(ent) {
++        size_t len = strlen(ent->d_name);
++        const char* prepos = strstr(ent->d_name, prefix.c_str());
++        const char* sufpos = strstr(ent->d_name, suffix.c_str());
++        if (prepos && sufpos + suffix.length() == ent->d_name + len) {
++            len -= (prepos - ent->d_name) + prefix.length() + suffix.length();
++            string name(prepos + prefix.length(), len);
++            string pluginpath = d;
++            if (pluginpath[pluginpath.length()-1] != '/') {
++                pluginpath.append("/");
++            }
++            pluginpath.append(ent->d_name);
++            // check that the file is a regular file
++            struct stat s;
++            if (stat(pluginpath.c_str(), &s) == 0 && (S_IFREG & s.st_mode)) {
++                modules.loadModule(name, pluginpath);
++            }
++        }
++        ent = readdir(dir);
++    }
++    closedir(dir);
++}
++vector<string>
++IndexPluginLoader::indexNames() {
++    vector<string> names;
++    map<string, Module*>::const_iterator i = modules.mods().begin();
++    for (; i != modules.mods().end(); ++i) {
++        names.push_back(i->first);
++    }
++    return names;
++}
++IndexManager*
++IndexPluginLoader::createIndexManager(const char* name, const char* dir) {
++    // find the right plugin
++    map<string, Module*>::iterator i = modules.mods().find(name);
++    if (i == modules.mods().end()) {
++        return 0;
++    }
++    // create the indexmanager
++    IndexManager* im = i->second->create(dir);
++    if (im) {
++        // map the indexmanager to the module that created it, so we can delete
++        // it later
++        modules.indexmanagers[im] = i->second;
++    }
++    return im;
++}
++void
++IndexPluginLoader::deleteIndexManager(IndexManager* im) {
++    // find the right module
++    map<void*, Module*>::iterator i = modules.indexmanagers.find(im);
++    if (i == modules.indexmanagers.end()) {
++        return;
++    }
++    // let the module delete the indexmanager
++    i->second->destroy(im);
++    // remove the mapping from the map
++    modules.indexmanagers.erase(i);
++}
+--- /dev/null
++++ b/src/streamanalyzer/indexpluginloader.h
+@@ -0,0 +1,34 @@
++/* This file is part of Strigi Desktop Search
++ *
++ * Copyright (C) 2007 Jos van den Oever <jos at vandenoever.info>
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public License
++ * along with this library; see the file COPYING.LIB.  If not, write to
++ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
++ * Boston, MA 02110-1301, USA.
++ */
++#include <strigi/strigiconfig.h>
++#include <vector>
++#include <map>
++#include <string>
++
++namespace Strigi {
++  class IndexManager;
++  namespace IndexPluginLoader {
++    STRIGI_EXPORT void loadPlugins(const char* dir);
++    STRIGI_EXPORT std::vector<std::string> indexNames();
++    STRIGI_EXPORT Strigi::IndexManager* createIndexManager(const char* name,
++        const char* dir);
++    STRIGI_EXPORT void deleteIndexManager(Strigi::IndexManager* manager);
++  }
++}
+--- a/src/streamanalyzer/indexreader.h
++++ b/src/streamanalyzer/indexreader.h
+@@ -79,7 +79,7 @@
+      *                 @p parent will be placed.
+      **/
+     virtual void getChildren(const std::string& parent,
+-            std::map<std::string, time_t>& children) {}
++            std::map<std::string, time_t>& children) {};
+     /**
+      * Count the number of documents indexed in the index.
+      *
+--- a/src/streamanalyzer/queryparser.cpp
++++ b/src/streamanalyzer/queryparser.cpp
+@@ -120,7 +120,19 @@
+     }
+     return space+1;
+ }
+-
++void
++prependXesamNamespace(Query& query) {
++    // prepend the field names with the xesam namespace
++    // this will be elaborated once the xesam spec continues
++    vector<string>::iterator end(query.fields().end());
++    for (vector<string>::iterator i = query.fields().begin(); i != end; ++i) {
++        *i = "http://freedesktop.org/standards/xesam/1.0/core#" + *i;
++    }
++    std::vector<Query>::iterator qend(query.subQueries().end());
++    for (vector<Query>::iterator i = query.subQueries().begin(); i!=qend; ++i) {
++        prependXesamNamespace(*i);
++    }
++}
+ Query
+ QueryParser::buildQuery(const std::string& q) {
+     Query query;
+@@ -140,14 +152,7 @@
+         Query q = query.subQueries()[0];
+         query = q;
+     }
++    prependXesamNamespace(query);
+ 
+-    // prepend the field names with the xesam namespace
+-    // this will be elaborated once the xesam spec continues
+-    vector<string>::iterator end(query.fields().end());
+-    for (vector<string>::iterator i = query.fields().begin(); i != end; ++i) {
+-         *i = "http://freedesktop.org/standards/xesam/1.0/core#" + *i;
+-    }
+-    //cerr << "query: '" << q << "' : " << query.subQueries().size() << "'"
+-    //    << query.term().string() << "'" << endl;
+     return query;
+ }
+--- a/src/streams/base64inputstream.cpp
++++ b/src/streams/base64inputstream.cpp
+@@ -71,6 +71,7 @@
+ Base64InputStream::Base64InputStream(InputStream* i) :p(new Private(this, i)) {
+ }
+ Base64InputStream::~Base64InputStream() {
++    delete p;
+ }
+ Base64InputStream::Private::Private(Base64InputStream* bi, InputStream* i)
+         :p(bi), input(i) {
+--- a/src/streams/CMakeLists.txt
++++ b/src/streams/CMakeLists.txt
+@@ -73,7 +73,6 @@
+ 	stringterminatedsubstream.h
+ 	subinputstream.h
+         textutils.h
+-	strigi/jstreamsconfig.h
+ 	DESTINATION include/strigi
+ )
+ install(TARGETS streams
+--- a/src/streams/rpminputstream.cpp
++++ b/src/streams/rpminputstream.cpp
+@@ -141,15 +141,9 @@
+     m_status = cpio->status();
+ }
+ RpmInputStream::~RpmInputStream() {
+-    if (uncompressionStream) {
+-        delete uncompressionStream;
+-    }
+-    if (cpio) {
+-        delete cpio;
+-    }
+-    if (headerinfo) {
+-        delete headerinfo;
+-    }
++    delete uncompressionStream;
++    delete cpio;
++    delete headerinfo;
+ }
+ InputStream*
+ RpmInputStream::nextEntry() {
+--- a/src/streams/strigi/strigiconfig.h.cmake
++++ b/src/streams/strigi/strigiconfig.h.cmake
+@@ -47,7 +47,7 @@
+ // our needed types
+ #if !@HAVE_INT8_T@
+  #define HAVE_INT8_T 1
+- #if ${SIZEOF_CHAR}==1 //is char 1bit?
++ #if ${SIZEOF_CHAR}==1 //is char one byte?
+   typedef char int8_t;
+  #else
+   #error Could not determine type for int8_t!
+@@ -56,7 +56,7 @@
+ 
+ #if !@HAVE_UINT8_T@
+  #define HAVE_UINT8_T 1
+- #if ${SIZEOF_CHAR}==1 //is char 1bit?
++ #if ${SIZEOF_CHAR}==1 //is char one byte?
+   typedef unsigned char uint8_t;
+  #else
+   #error Could not determine type for uint8_t!
+@@ -65,7 +65,7 @@
+ 
+ #if !@HAVE_INT16_T@
+  #define HAVE_INT16_T 1
+- #if ${SIZEOF_SHORT}==2 //is short 2bits?
++ #if ${SIZEOF_SHORT}==2 //is short two bytes?
+   typedef short int16_t;
+  #else
+   #error Could not determine type for int16_t!
+@@ -74,7 +74,7 @@
+ 
+ #if !@HAVE_UINT16_T@
+  #define HAVE_UINT16_T 1
+- #if ${SIZEOF_SHORT}==2 //is short 2bits?
++ #if ${SIZEOF_SHORT}==2 //is short two bytes?
+   typedef unsigned short uint16_t;
+  #else
+   #error Could not determine type for uint16_t!
+@@ -83,9 +83,9 @@
+ 
+ #if !@HAVE_INT32_T@
+  #define HAVE_INT32_T 1
+- #if ${SIZEOF_INT}==4 //is int 4bits?
++ #if ${SIZEOF_INT}==4 //is int four bytes?
+   typedef int int32_t;
+- #elif ${SIZEOF_LONG}==4 //is long 4bits?
++ #elif ${SIZEOF_LONG}==4 //is long four bytes?
+   typedef long int32_t;
+  #else
+   #error Could not determine type for int32_t!
+@@ -94,9 +94,9 @@
+ 
+ #if !@HAVE_UINT32_T@
+  #define HAVE_UINT32_T 1
+- #if ${SIZEOF_INT}==4 //is int 4bits?
++ #if ${SIZEOF_INT}==4 //is int four bytes?
+   typedef unsigned int uint32_t;
+- #elif ${SIZEOF_LONG}==4 //is long 4bits?
++ #elif ${SIZEOF_LONG}==4 //is long four bytes?
+   typedef unsigned long uint32_t;
+  #else
+   #error Could not determine type for uint32_t!
+@@ -132,16 +132,6 @@
+  #define HAVE_UINT 1
+ #endif
+ 
+-#if !@HAVE_INTPTR_T@
+- typedef int intptr_t;
+- #define HAVE_INTPTR_T 1
+-#endif
+-
+-#if !@HAVE_SOCKLEN_T@
+- typedef int socklen_t;
+- #define HAVE_SOCKLEN_T 1
+-#endif
+-
+ #if !@HAVE_SIZE_T@
+  #ifndef _SIZE_T_DEFINED 
+   #ifndef HAVE_SIZE_T
+@@ -152,16 +142,6 @@
+  #endif
+ #endif
+ 
+-#if !@HAVE_SSIZE_T@
+- #ifndef _SSIZE_T_DEFINED 
+-  #ifndef HAVE_SSIZE_T
+-   typedef signed int ssize_t;
+-   #define HAVE_SSIZE_T 1
+-  #endif
+-  #define _SSIZE_T_DEFINED 1    // kdewin32 define
+- #endif
+-#endif
+-
+ #cmakedefine __STRIGI_HAVE_GCC_VISIBILITY
+ 
+ #cmakedefine ENABLE_NEWXESAM
+@@ -175,7 +155,7 @@
+  */
+ #ifdef __STRIGI_HAVE_GCC_VISIBILITY
+ #define STRIGI_EXPORT __attribute__ ((visibility("default")))
+-#define STRIGI_IMPORT STRIGI_EXPORT
++#define STRIGI_IMPORT
+ #elif defined(_WIN32) || defined(_WIN64)
+ #define STRIGI_EXPORT __declspec(dllexport)
+ #define STRIGI_IMPORT __declspec(dllimport)
+@@ -200,14 +180,6 @@
+ # endif
+ #endif
+ 
+-#ifndef CLUCENEINDEXER_EXPORT
+-# ifdef MAKE_CLUCENEINDEXER_LIB
+-#  define CLUCENEINDEXER_EXPORT STRIGI_EXPORT
+-# else
+-#  define CLUCENEINDEXER_EXPORT STRIGI_IMPORT
+-# endif
+-#endif
+-
+ #ifndef STRIGI_QTDBUSCLIENT_EXPORT
+ # ifdef MAKE_STRIGI_QTDBUSCLIENT_LIB
+ #  define STRIGI_QTDBUSCLIENT_EXPORT STRIGI_EXPORT
+--- a/src/strigicmd/strigicmd.cpp
++++ b/src/strigicmd/strigicmd.cpp
+@@ -18,7 +18,8 @@
+  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+  * Boston, MA 02110-1301, USA.
+  */
+-#include "combinedindexmanager.h"
++#include "indexpluginloader.h"
++#include "indexmanager.h"
+ #include "indexreader.h"
+ #include "indexwriter.h"
+ #include "indexeddocument.h"
+@@ -154,6 +155,10 @@
+ }
+ void
+ printBackends(const string& msg, const vector<string> backends) {
++    if (backends.size() == 0) {
++        pe(" No backends are available.\n");
++        return;
++    }
+     pe(msg.c_str());
+     pe(" Choose one from ");
+     for (uint j=0; j<backends.size()-1; ++j) {
+@@ -218,7 +223,7 @@
+ IndexManager*
+ getIndexManager(string& backend, const string& indexdir) {
+     // check arguments: backend
+-    const vector<string>& backends = CombinedIndexManager::backEnds();
++    const vector<string>& backends = IndexPluginLoader::indexNames();
+     // if there is only one backend, the backend does not have to be specified
+     if (backend.size() == 0) {
+         if (backends.size() == 1) {
+@@ -230,11 +235,13 @@
+     }
+     vector<string>::const_iterator b
+         = find(backends.begin(), backends.end(), backend);
++cerr << "n backends: " << backends.size() << endl;
+     if (b == backends.end()) {
+         printBackends("Invalid index type.", backends);
+         return 0;
+     }
+-    return CombinedIndexManager::factories()[backend](indexdir.c_str());
++    return IndexPluginLoader::createIndexManager(backend.c_str(),
++        indexdir.c_str());
+ }
+ int
+ create(int argc, char** argv) {
+@@ -286,7 +293,7 @@
+         analyzer->analyzeDir(j->c_str(), nthreads);
+     }
+     delete analyzer;
+-    delete manager;
++    IndexPluginLoader::deleteIndexManager(manager);
+ 
+     return 0;
+ }
+@@ -329,7 +336,7 @@
+     DirAnalyzer* analyzer = new DirAnalyzer(*manager, config);
+     analyzer->updateDirs(arguments, nthreads);
+     delete analyzer;
+-    delete manager;
++    IndexPluginLoader::deleteIndexManager(manager);
+ 
+     return 0;
+ }
+@@ -363,7 +370,7 @@
+     }
+     IndexReader* reader = manager->indexReader();
+     listFiles(reader, "");
+-    delete manager;
++    IndexPluginLoader::deleteIndexManager(manager);
+     return 0;
+ }
+ int
+@@ -411,7 +418,7 @@
+         }
+     }
+     
+-    delete manager;
++    IndexPluginLoader::deleteIndexManager(manager);
+     return 0;
+ }
+ int
+@@ -478,7 +485,7 @@
+         }
+     }
+     
+-    delete manager;
++    IndexPluginLoader::deleteIndexManager(manager);
+     return 0;
+ }
+ int
+@@ -572,7 +579,7 @@
+     if (results != 0)
+         printf ("Query returned %i results\n", results);
+ 
+-    delete manager;
++    IndexPluginLoader::deleteIndexManager(manager);
+     return 0;
+ }
+ int
+@@ -645,7 +652,7 @@
+         writer->optimize();
+     }
+     
+-    delete manager;
++    IndexPluginLoader::deleteIndexManager(manager);
+     return 0;
+ }
+ int
+@@ -672,7 +679,7 @@
+     for (i=fields.begin(); i!=fields.end(); ++i) {
+         printf("%s\n", i->c_str());
+     }
+-    delete manager;
++    IndexPluginLoader::deleteIndexManager(manager);
+     return 0;
+ }
+ int
+--- a/tests/CMakeLists.txt
++++ b/tests/CMakeLists.txt
+@@ -1,28 +1,21 @@
+-set (TESTINGDIRS ${TESTINGDIRS} utils indextesters streamanalyzer)
++set (TESTINGDIRS utils indextesters streamanalyzer daemon)
++subdirs (${TESTINGDIRS})
++
++# setting for using CPPUNIT
+ 
+-if (CLucene_FOUND OR HyperEstraier_FOUND OR SQLite_FOUND)
+-  set(TESTINGDIRS ${TESTINGDIRS} daemon)
+-endif (CLucene_FOUND OR HyperEstraier_FOUND OR SQLite_FOUND)
++include_directories (. ${CPPUNIT_INCLUDE_DIR}  ${CMAKE_SOURCE_DIR}/src/daemon
++    ${CMAKE_BINARY_DIR}/src/streams)
+ 
+ # cppunit requires exception support
+ IF(NOT WIN32)
+     set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions")
+ ENDIF(NOT WIN32)
+ 
+-# disable, needs some testing
+-#if (HyperEstraier_FOUND)
+-#  set (TESTINGDIRS ${TESTINGDIRS} estraierindexer)
+-#endif (HyperEstraier_FOUND)
+-
+-if (CLucene_FOUND)
+-  set(TESTINGDIRS ${TESTINGDIRS} luceneindexer)
+-endif (CLucene_FOUND)
+-
+-include_directories (. ${CPPUNIT_INCLUDE_DIR} ${strigi_SOURCE_DIR}/src/daemon)
+-
++# a convenience library that adds a unified way of build a test executable
++# for testing
++# simply link this into any unit test executable
+ add_library(test_runner test_runner.cpp)
+ target_link_libraries(test_runner ${CPPUNIT_LIBRARIES})
+ 
+- ENABLE_TESTING()
++ENABLE_TESTING()
+ 
+-subdirs (${TESTINGDIRS})
+--- a/tests/daemon/CMakeLists.txt
++++ b/tests/daemon/CMakeLists.txt
+@@ -1,8 +1,5 @@
+ # add a test for the daemon configuration loading classes
+ 
+-# fancy way of saying set(INC_DIR test/daemon)
+-string(REGEX REPLACE /test /src INC_DIR ${CMAKE_CURRENT_SOURCE_DIR})
+-
+ # if we use log4cxx, include it
+ # ideally this should be abstracted away in something like STRIGILOG( ... )
+ if (ENABLE_LOG4CXX AND Log4cxx_FOUND)
+--- a/tests/estraierindexer/CMakeLists.txt
++++ /dev/null
+@@ -1,26 +0,0 @@
+-STRING(REGEX REPLACE /test /src INC_DIR ${CMAKE_CURRENT_SOURCE_DIR})
+-
+-if (ENABLE_LOG4CXX AND Log4cxx_FOUND)
+-    set(estraiertest_LIBS ${estraiertest_LIBS} ${LOG4CXX_LIBRARIES})
+-    set (INC_DIR ${INC_DIR} ${LOG4CXX_INCLUDE_DIR})
+-    add_definitions(-DHAVE_LOG4CXX)
+-endif (ENABLE_LOG4CXX AND Log4cxx_FOUND)
+-
+-include_directories (. .. ${INC_DIR}
+-                     ../indextests
+-                     ${strigi_SOURCE_DIR}/src/streamanalyzer
+-                     ${strigi_SOURCE_DIR}/src/streams
+-                     ${strigi_BINARY_DIR}/src/streams
+-                     ${strigi_SOURCE_DIR}/src/streams/strigi
+-                     ${EST_INCLUDE_DIR}
+-)
+-
+-add_library(estraiertest SHARED   estraierindexmanagertest.cpp
+-                                ../indextests/indexmanagertester.cpp
+-                                estraierindexreadertest.cpp
+-                                ../indextests/indexreadertester.cpp
+-                                estraierindexwritertest.cpp
+-                                ../indextests/indexwritertester.cpp )
+-
+-target_link_libraries (estraiertest estraierindex ${estraiertest_LIBS})
+-add_test (estraiertest estraiertest)
+--- a/tests/estraierindexer/estraierindexmanagertest.cpp
++++ /dev/null
+@@ -1,72 +0,0 @@
+-/* This file is part of Strigi Desktop Search
+- *
+- * Copyright (C) 2007 Flavio Castelli <flavio.castelli at gmail.com>
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Library General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * Library General Public License for more details.
+- *
+- * You should have received a copy of the GNU Library General Public License
+- * along with this library; see the file COPYING.LIB.  If not, write to
+- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+- * Boston, MA 02110-1301, USA.
+- */
+-#include "estraierindexmanagertest.h"
+-
+-#include "analysisresult.h"
+-#include "analyzerconfiguration.h"
+-#include "estraierindexmanager.h"
+-#include "indexwriter.h"
+-#include "indexreader.h"
+-#include "query.h"
+-
+-#include <string>
+-#include <sstream>
+-#include <sys/stat.h>
+-#include <sys/types.h>
+-#include <stdlib.h>
+-#ifdef _WIN32
+-#include <direct.h>
+-#endif
+-
+-using namespace std;
+-using namespace strigiunittest;
+-
+-// Registers the fixture into the 'registry'
+-CPPUNIT_TEST_SUITE_REGISTRATION( EstraierIndexManagerTest );
+-
+-void EstraierIndexManagerTest::setUp()
+-{
+-    IndexManagerTester::setUp();
+-    
+-    path = "testestraierindex";
+-
+-    // initialize a directory for writing and an indexmanager
+-#ifdef _WIN32
+-    mkdir(path.c_str());
+-#else
+-    mkdir(path.c_str(), S_IRUSR|S_IWUSR|S_IXUSR);
+-#endif
+-
+-    manager = new EstraierIndexManager(path.c_str());
+-    writer = manager->getIndexWriter();
+-    reader = manager->getIndexReader();
+-    ic = new Strigi::AnalyzerConfiguration ();
+-    si = new Strigi::StreamAnalyzer (*ic);
+-}
+-
+-void EstraierIndexManagerTest::tearDown()
+-{
+-    IndexManagerTester::tearDown();
+-    
+-    // clean up data
+-    string cmd = "rm -r ";
+-    cmd += path;
+-    system(cmd.c_str());
+-}
+--- a/tests/estraierindexer/estraierindexmanagertest.h
++++ /dev/null
+@@ -1,43 +0,0 @@
+-/* This file is part of Strigi Desktop Search
+- *
+- * Copyright (C) 2007 Flavio Castelli <flavio.castelli at gmail.com>
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Library General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * Library General Public License for more details.
+- *
+- * You should have received a copy of the GNU Library General Public License
+- * along with this library; see the file COPYING.LIB.  If not, write to
+- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+- * Boston, MA 02110-1301, USA.
+- */
+-#ifndef UNIT_TEST_ESTRAIER_INDEX_MANAGER_TEST_H
+-#define UNIT_TEST_ESTRAIER_INDEX_MANAGER_TEST_H
+-
+-#include "indexmanagertester.h"
+-
+-namespace strigiunittest
+-{
+-    class EstraierIndexManagerTest : public IndexManagerTester
+-    {
+-        CPPUNIT_TEST_SUB_SUITE( EstraierIndexManagerTest,  IndexManagerTester);
+-        CPPUNIT_TEST( testVariables );
+-        //CPPUNIT_TEST( runUnthreadedTests );
+-        //CPPUNIT_TEST( runThreadedTests );
+-        CPPUNIT_TEST( addAndCount );
+-        CPPUNIT_TEST( testNumberQuery );
+-        CPPUNIT_TEST_SUITE_END();
+-        
+-        public:
+-            void setUp();
+-            void tearDown();
+-    };
+-}
+-
+-#endif
+--- a/tests/estraierindexer/estraierindexreadertest.cpp
++++ /dev/null
+@@ -1,69 +0,0 @@
+-/* This file is part of Strigi Desktop Search
+- *
+- * Copyright (C) 2007 Flavio Castelli <flavio.castelli at gmail.com>
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Library General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * Library General Public License for more details.
+- *
+- * You should have received a copy of the GNU Library General Public License
+- * along with this library; see the file COPYING.LIB.  If not, write to
+- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+- * Boston, MA 02110-1301, USA.
+- */
+-#include "estraierindexreadertest.h"
+-
+-#include "analysisresult.h"
+-#include "analyzerconfiguration.h"
+-#include "estraierindexmanager.h"
+-#include "indexwriter.h"
+-#include "indexreader.h"
+-#include "query.h"
+-
+-#include <string>
+-#include <sstream>
+-#include <sys/stat.h>
+-#include <sys/types.h>
+-#include <stdlib.h>
+-#ifdef _WIN32
+-#include <direct.h>
+-#endif
+-
+-using namespace std;
+-using namespace strigiunittest;
+-
+-// Registers the fixture into the 'registry'
+-CPPUNIT_TEST_SUITE_REGISTRATION( EstraierIndexReaderTest );
+-
+-void EstraierIndexReaderTest::setUp()
+-{
+-    IndexReaderTester::setUp();
+-    
+-    path = "testestraier";
+-
+-    // initialize a directory for writing and an indexmanager
+-#ifdef _WIN32
+-    mkdir(path.c_str());
+-#else
+-    mkdir(path.c_str(), S_IRUSR|S_IWUSR|S_IXUSR);
+-#endif
+-
+-    manager = new EstraierIndexManager(path.c_str());
+-    reader = manager->getIndexReader();
+-}
+-
+-void EstraierIndexReaderTest::tearDown()
+-{
+-    IndexReaderTester::tearDown();
+-    
+-    // clean up data
+-    string cmd = "rm -r ";
+-    cmd += path;
+-    system(cmd.c_str());
+-}
+--- a/tests/estraierindexer/estraierindexreadertest.h
++++ /dev/null
+@@ -1,40 +0,0 @@
+-/* This file is part of Strigi Desktop Search
+- *
+- * Copyright (C) 2007 Flavio Castelli <flavio.castelli at gmail.com>
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Library General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * Library General Public License for more details.
+- *
+- * You should have received a copy of the GNU Library General Public License
+- * along with this library; see the file COPYING.LIB.  If not, write to
+- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+- * Boston, MA 02110-1301, USA.
+- */
+-#ifndef UNIT_TEST_ESTRAIER_INDEX_READER_TEST_H
+-#define UNIT_TEST_ESTRAIER_INDEX_READER_TEST_H
+-
+-#include "indexreadertester.h"
+-
+-namespace strigiunittest
+-{
+-    class EstraierIndexReaderTest : public IndexReaderTester
+-    {
+-        CPPUNIT_TEST_SUB_SUITE( EstraierIndexReaderTest,  IndexReaderTester);
+-        CPPUNIT_TEST( testVariables );
+-        CPPUNIT_TEST( getFiles );
+-        CPPUNIT_TEST_SUITE_END();
+-        
+-        public:
+-            void setUp();
+-            void tearDown();
+-    };
+-}
+-
+-#endif
+--- a/tests/estraierindexer/estraierindexwritertest.cpp
++++ /dev/null
+@@ -1,70 +0,0 @@
+-/* This file is part of Strigi Desktop Search
+- *
+- * Copyright (C) 2007 Flavio Castelli <flavio.castelli at gmail.com>
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Library General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * Library General Public License for more details.
+- *
+- * You should have received a copy of the GNU Library General Public License
+- * along with this library; see the file COPYING.LIB.  If not, write to
+- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+- * Boston, MA 02110-1301, USA.
+- */
+-#include "estraierindexwritertest.h"
+-
+-#include "analysisresult.h"
+-#include "analyzerconfiguration.h"
+-#include "estraierindexmanager.h"
+-#include "indexwriter.h"
+-#include "query.h"
+-
+-#include <string>
+-#include <sstream>
+-#include <sys/stat.h>
+-#include <sys/types.h>
+-#include <stdlib.h>
+-#ifdef _WIN32
+-#include <direct.h>
+-#endif
+-
+-using namespace std;
+-using namespace strigiunittest;
+-
+-// Registers the fixture into the 'registry'
+-CPPUNIT_TEST_SUITE_REGISTRATION( EstraierIndexWriterTest );
+-
+-void EstraierIndexWriterTest::setUp()
+-{
+-    IndexWriterTester::setUp();
+-    
+-    path = "testestraierindex";
+-
+-    // initialize a directory for writing and an indexmanager
+-#ifdef _WIN32
+-    mkdir(path.c_str());
+-#else
+-    mkdir(path.c_str(), S_IRUSR|S_IWUSR|S_IXUSR);
+-#endif
+-
+-    manager = new EstraierIndexManager(path.c_str());
+-    writer = manager->getIndexWriter();
+-    ic = new Strigi::AnalyzerConfiguration ();
+-    si = new Strigi::StreamAnalyzer (*ic);
+-}
+-
+-void EstraierIndexWriterTest::tearDown()
+-{
+-    IndexWriterTester::tearDown();
+-    
+-    // clean up data
+-    string cmd = "rm -r ";
+-    cmd += path;
+-    system(cmd.c_str());
+-}
+--- a/tests/estraierindexer/estraierindexwritertest.h
++++ /dev/null
+@@ -1,41 +0,0 @@
+-/* This file is part of Strigi Desktop Search
+- *
+- * Copyright (C) 2007 Flavio Castelli <flavio.castelli at gmail.com>
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Library General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * Library General Public License for more details.
+- *
+- * You should have received a copy of the GNU Library General Public License
+- * along with this library; see the file COPYING.LIB.  If not, write to
+- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+- * Boston, MA 02110-1301, USA.
+- */
+-#ifndef UNIT_TEST_ESTRAIER_INDEX_WRITER_TEST_H
+-#define UNIT_TEST_ESTRAIER_INDEX_WRITER_TEST_H
+-
+-#include "indexwritertester.h"
+-
+-namespace strigiunittest
+-{
+-    class EstraierIndexWriterTest : public IndexWriterTester
+-    {
+-        CPPUNIT_TEST_SUB_SUITE( EstraierIndexWriterTest,  IndexWriterTester);
+-        CPPUNIT_TEST( testVariables );
+-        CPPUNIT_TEST( add );
+-        CPPUNIT_TEST( optimize );
+-        CPPUNIT_TEST_SUITE_END();
+-        
+-        public:
+-            void setUp();
+-            void tearDown();
+-    };
+-}
+-
+-#endif
+--- /dev/null
++++ b/tests/indextesters/clucenetests.cpp
+@@ -0,0 +1,52 @@
++/* This file is part of Strigi Desktop Search
++ *
++ * Copyright (C) 2007 Jos van den Oever <jos at vandenoever.info>
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public License
++ * along with this library; see the file COPYING.LIB.  If not, write to
++ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
++ * Boston, MA 02110-1301, USA.
++ */
++
++#include "indexreadertester.h"
++#include "indexwritertester.h"
++#include "indexsearchtester.h"
++using namespace strigiunittest;
++
++class CLuceneIndexReaderTest : public IndexReaderTest {
++private:
++    CPPUNIT_TEST_SUB_SUITE( CLuceneIndexReaderTest, IndexReaderTest);
++    CPPUNIT_TEST_SUITE_END();
++public:
++    CLuceneIndexReaderTest() :IndexReaderTest("clucene") {}
++};
++CPPUNIT_TEST_SUITE_REGISTRATION( CLuceneIndexReaderTest );
++
++class CLuceneIndexWriterTest : public IndexWriterTest {
++private:
++    CPPUNIT_TEST_SUB_SUITE( CLuceneIndexWriterTest, IndexWriterTest);
++    CPPUNIT_TEST_SUITE_END();
++public:
++    CLuceneIndexWriterTest() :IndexWriterTest("clucene") {}
++};
++CPPUNIT_TEST_SUITE_REGISTRATION( CLuceneIndexWriterTest );
++
++class CLuceneIndexSearchTest : public IndexSearchTest {
++private:
++    CPPUNIT_TEST_SUB_SUITE( CLuceneIndexSearchTest, IndexSearchTest);
++    CPPUNIT_TEST_SUITE_END();
++public:
++    CLuceneIndexSearchTest() :IndexSearchTest("clucene") {}
++};
++CPPUNIT_TEST_SUITE_REGISTRATION( CLuceneIndexSearchTest );
++
+--- a/tests/indextesters/CMakeLists.txt
++++ b/tests/indextesters/CMakeLists.txt
+@@ -1,6 +1,6 @@
+ if (ENABLE_LOG4CXX AND Log4cxx_FOUND)
+-  set(indextesters_LIBS ${indextesters_LIBS} ${LOG4CXX_LIBRARIES})
+-  set (INC_DIR ${INC_DIR} ${LOG4CXX_INCLUDE_DIR})
++  set(indextesters_LIBS ${LOG4CXX_LIBRARIES})
++  set(INC_DIR ${LOG4CXX_INCLUDE_DIR})
+   add_definitions(-DHAVE_LOG4CXX)
+ endif (ENABLE_LOG4CXX AND Log4cxx_FOUND)
+ 
+@@ -12,10 +12,26 @@
+   ../utils
+ )
+ 
+-add_library(indextesters indexmanagertester.cpp
+-                         indexreadertester.cpp
+-                         indexwritertester.cpp
+-                         indexsearchtester.cpp
+-)
++set(indextester_SRCS indextest.cpp indexreadertester.cpp indexwritertester.cpp
++    indexsearchtester.cpp)
++if (CLucene_FOUND)
++  set(indextester_SRCS ${indextester_SRCS} clucenetests.cpp)
++  set (indextester_DEPS ${indextester_DEPS} clucene)
++endif (CLucene_FOUND)
++if (ENABLE_SQLITE AND SQLite_FOUND)
++  set (indextester_SRCS ${indextester_SRCS} sqlitetests.cpp)
++  set (indextester_DEPS sqlite)
++endif (ENABLE_SQLITE AND SQLite_FOUND)
++if (HyperEstraier_FOUND)
++  set (indextester_SRCS ${indextester_SRCS} estraiertests.cpp)
++  set (indextester_DEPS estraier)
++endif (HyperEstraier_FOUND)
++
++add_executable(indextester ${indextester_SRCS})
++if (indextester_DEPS)
++  ADD_DEPENDENCIES(indextester ${indextester_DEPS})
++endif (indextester_DEPS)
++target_link_libraries(indextester
++  test_runner unittestfunctions ${indextesters_LIBS})
+ 
+-target_link_libraries (indextesters unittestfunctions ${indextesters_LIBS})
++add_test(indextester indextester)
+--- /dev/null
++++ b/tests/indextesters/estraiertests.cpp
+@@ -0,0 +1,52 @@
++/* This file is part of Strigi Desktop Search
++ *
++ * Copyright (C) 2007 Jos van den Oever <jos at vandenoever.info>
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public License
++ * along with this library; see the file COPYING.LIB.  If not, write to
++ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
++ * Boston, MA 02110-1301, USA.
++ */
++
++#include "indexreadertester.h"
++#include "indexwritertester.h"
++#include "indexsearchtester.h"
++using namespace strigiunittest;
++
++class EstraierIndexReaderTest : public IndexReaderTest {
++private:
++    CPPUNIT_TEST_SUB_SUITE( EstraierIndexReaderTest, IndexReaderTest);
++    CPPUNIT_TEST_SUITE_END();
++public:
++    EstraierIndexReaderTest() :IndexReaderTest("estraier") {}
++};
++CPPUNIT_TEST_SUITE_REGISTRATION( EstraierIndexReaderTest );
++
++class EstraierIndexWriterTest : public IndexWriterTest {
++private:
++    CPPUNIT_TEST_SUB_SUITE( EstraierIndexWriterTest, IndexWriterTest);
++    CPPUNIT_TEST_SUITE_END();
++public:
++    EstraierIndexWriterTest() :IndexWriterTest("estraier") {}
++};
++CPPUNIT_TEST_SUITE_REGISTRATION( EstraierIndexWriterTest );
++
++
++class EstraierIndexSearchTest : public IndexSearchTest {
++private:
++    CPPUNIT_TEST_SUB_SUITE( EstraierIndexSearchTest, IndexSearchTest);
++    CPPUNIT_TEST_SUITE_END();
++public:
++    EstraierIndexSearchTest() :IndexSearchTest("estraier") {}
++};
++CPPUNIT_TEST_SUITE_REGISTRATION( EstraierIndexSearchTest );
+--- a/tests/indextesters/indexmanagertester.cpp
++++ b/tests/indextesters/indexmanagertester.cpp
+@@ -18,53 +18,41 @@
+  * Boston, MA 02110-1301, USA.
+  */
+ #include "indexmanagertester.h"
+-
+-#include "analysisresult.h"
+-#include "analyzerconfiguration.h"
+ #include "indexmanager.h"
+-#include "indexwriter.h"
+-#include "indexreader.h"
+-#include "fieldtypes.h"
+-#include "query.h"
+-#include "queryparser.h"
+-
+-#include <sstream>
+-#include <sys/stat.h>
+-#include <sys/types.h>
+-#include <stdlib.h>
+-#ifdef _WIN32
+-#include <direct.h>
+-#endif
++#include "indexpluginloader.h"
+ 
+ using namespace std;
+ using namespace Strigi;
+ using namespace strigiunittest;
+ 
+-void IndexManagerTester::setUp()
+-{
+-    m_manager = createManager();
+-}
++CPPUNIT_TEST_SUITE_REGISTRATION( CLuceneIndexManagerTest );
+ 
+-void IndexManagerTester::tearDown()
+-{
+-    deleteManager( m_manager );
++IndexManagerTest::IndexManagerTest(const std::string& backendname)
++    :m_backendname(backendname), m_indexpath(":memory:"), m_manager(0) {
+ }
+ 
+-
+-void IndexManagerTester::deleteManager( Strigi::IndexManager* m )
+-{
+-    delete m;
++void
++IndexManagerTest::setUp() {
++    m_manager = Strigi::IndexPluginLoader::createIndexManager(
++        m_backendname.c_str(), m_indexpath.c_str());
+ }
+ 
++void
++IndexManagerTest::tearDown() {
++    Strigi::IndexPluginLoader::deleteIndexManager(m_manager);
++    // clean up data (if any)
++    string cmd("rm -rf '" + m_indexpath + "'");
++    system(cmd.c_str());
++}
+ 
+-void IndexManagerTester::testIndexReader()
+-{
++void
++IndexManagerTest::testIndexReader() {
+     Strigi::IndexReader* reader = m_manager->indexReader();
+     CPPUNIT_ASSERT_MESSAGE("reader creation failed", reader);
+ }
+ 
+-void IndexManagerTester::testIndexWriter()
+-{
++void
++IndexManagerTest::testIndexWriter() {
+     Strigi::IndexWriter* writer = m_manager->indexWriter();
+     CPPUNIT_ASSERT_MESSAGE("writer creation failed", writer);
+ }
+--- a/tests/indextesters/indexmanagertester.h
++++ b/tests/indextesters/indexmanagertester.h
+@@ -30,34 +30,37 @@
+     class IndexReader;
+ }
+ 
+-namespace strigiunittest
+-{
+-    class IndexManagerTester : public CppUnit::TestFixture
+-    {
+-        CPPUNIT_TEST_SUITE( IndexManagerTester );
+-        CPPUNIT_TEST( testIndexReader );
+-        CPPUNIT_TEST( testIndexWriter );
+-        CPPUNIT_TEST_SUITE_END_ABSTRACT();
+-
+-    private:
+-	Strigi::IndexManager* m_manager;
+-
+-    protected:
+-	virtual Strigi::IndexManager* createManager() = 0;
+-
+-	/**
+-	 * delete the manager. The default implementation simply
+-	 * calls delete.
+-	 */
+-	virtual void deleteManager( Strigi::IndexManager* );
+-        
+-    public:
+-	virtual void setUp();
+-	virtual void tearDown();
+-            
+-	virtual void testIndexReader();
+-	virtual void testIndexWriter();
+-    };
+-}
++namespace strigiunittest {
++
++class IndexManagerTest : public CppUnit::TestFixture {
++private:
++    CPPUNIT_TEST_SUITE( IndexManagerTest );
++    CPPUNIT_TEST( testIndexReader );
++    CPPUNIT_TEST( testIndexWriter );
++    CPPUNIT_TEST_SUITE_END_ABSTRACT();
++
++    const std::string m_backendname;
++    const std::string m_indexpath;
++    Strigi::IndexManager* m_manager;
++
++protected:
++    IndexManagerTest(const std::string& backendname);
+ 
++public:
++    void setUp();
++    void tearDown();
++
++    void testIndexReader();
++    void testIndexWriter();
++};
++
++class CLuceneIndexManagerTest : public IndexManagerTest {
++private:
++    CPPUNIT_TEST_SUB_SUITE( CLuceneIndexManagerTest, IndexManagerTest);
++    CPPUNIT_TEST_SUITE_END();
++public:
++    CLuceneIndexManagerTest() :IndexManagerTest("clucene") {}
++};
++
++}
+ #endif
+--- a/tests/indextesters/indexreadertester.cpp
++++ b/tests/indextesters/indexreadertester.cpp
+@@ -20,61 +20,38 @@
+ #include "indexreadertester.h"
+ 
+ #include "analysisresult.h"
+-#include "analyzerconfiguration.h"
+-#include "indexmanager.h"
+ #include "indexwriter.h"
+ #include "indexreader.h"
+ #include "fieldtypes.h"
+-#include "analyzerconfiguration.h"
+ #include "query.h"
+ #include "queryparser.h"
+ 
+-#include <string>
+ #include <sstream>
+-#include <sys/stat.h>
+-#include <sys/types.h>
+-#include <stdlib.h>
+-#ifdef _WIN32
+-#include <direct.h>
+-#endif
+-
+ #include <ostream>
+ 
+ using namespace std;
+ using namespace strigiunittest;
+ using namespace Strigi;
+ 
+-void IndexReaderTester::setUp()
+-{
+-    m_manager = createManager();
+-    m_writer = m_manager->indexWriter();
+-    m_reader = m_manager->indexReader();
+-
+-    CPPUNIT_ASSERT_MESSAGE("writer creation failed", m_writer);
+-    CPPUNIT_ASSERT_MESSAGE("reader creation failed", m_reader);
+-
++void
++IndexReaderTest::setUp() {
++    IndexTest::setUp();
+     m_streamAnalyzer = new Strigi::StreamAnalyzer( m_analyzerConfiguration );
+ }
+ 
+-void IndexReaderTester::tearDown()
+-{
++void
++IndexReaderTest::tearDown() {
+     delete m_streamAnalyzer;
+-    deleteManager( m_manager );
+-}
+-
+-
+-void IndexReaderTester::deleteManager( Strigi::IndexManager* m )
+-{
+-    delete m;
++    IndexTest::tearDown();
+ }
+ 
+ void
+-IndexReaderTester::testChildrenRetrieval() {
++IndexReaderTest::testChildrenRetrieval() {
+     // FIXME
+ }
+ 
+-void IndexReaderTester::addAndCount()
+-{
++void
++IndexReaderTest::addAndCount() {
+     static const int m = 20;
+ 
+     m_writer->deleteAllEntries();
+@@ -93,8 +70,8 @@
+     CPPUNIT_ASSERT_EQUAL_MESSAGE(str.str(), m, n);
+ }
+ 
+-void IndexReaderTester::testNumberQuery()
+-{
++void
++IndexReaderTest::testNumberQuery() {
+     m_writer->deleteAllEntries();
+     // add numbers to the database
+     int m = 200;
+--- a/tests/indextesters/indexreadertester.h
++++ b/tests/indextesters/indexreadertester.h
+@@ -20,55 +20,37 @@
+ #ifndef UNIT_TEST_INDEX_READER_TESTER_H
+ #define UNIT_TEST_INDEX_READER_TESTER_H
+ 
+-#include <cppunit/TestFixture.h>
+-#include <cppunit/extensions/HelperMacros.h>
+-#include <string>
+-
++#include "indextest.h"
+ #include "analyzerconfiguration.h"
+-#include "fieldtypes.h"
+ 
+ namespace Strigi {
+-    class IndexManager;
+-    class IndexReader;
+-    class IndexWriter;
+     class StreamAnalyzer;
+ }
+ 
+-namespace strigiunittest
+-{
+-    class IndexReaderTester : public CppUnit::TestFixture
+-    {
+-        CPPUNIT_TEST_SUITE( IndexReaderTester );
+-        CPPUNIT_TEST( testChildrenRetrieval );
+-        CPPUNIT_TEST( addAndCount );
+-        CPPUNIT_TEST( testNumberQuery );
+-        CPPUNIT_TEST_SUITE_END_ABSTRACT();
+-        
+-    private:
+-	Strigi::IndexManager* m_manager;
+-
+-	Strigi::IndexWriter* m_writer;
+-	Strigi::IndexReader* m_reader;
+-	Strigi::StreamAnalyzer* m_streamAnalyzer;
+-	Strigi::AnalyzerConfiguration m_analyzerConfiguration;
+-	Strigi::FieldRegister m_fieldRegister;
+-
+-    protected:
+-	virtual Strigi::IndexManager* createManager() = 0;
+-	/**
+-	 * delete the manager. The default implementation simply
+-	 * calls delete.
+-	 */
+-	virtual void deleteManager( Strigi::IndexManager* );
+-
+-    public:
+-	virtual void setUp();
+-	virtual void tearDown();
+-            
+-	virtual void addAndCount();
+-	virtual void testChildrenRetrieval();
+-	virtual void testNumberQuery();
+-    };
++namespace strigiunittest {
++
++class IndexReaderTest : public IndexTest {
++private:
++    CPPUNIT_TEST_SUITE( IndexReaderTest );
++    CPPUNIT_TEST( testChildrenRetrieval );
++    CPPUNIT_TEST( addAndCount );
++    CPPUNIT_TEST( testNumberQuery );
++    CPPUNIT_TEST_SUITE_END_ABSTRACT();
++
++    Strigi::StreamAnalyzer* m_streamAnalyzer;
++    Strigi::AnalyzerConfiguration m_analyzerConfiguration;
++    Strigi::FieldRegister m_fieldRegister;
++
++    void addAndCount();
++    void testChildrenRetrieval();
++    void testNumberQuery();
++public:
++    IndexReaderTest(const std::string& backendname) :IndexTest(backendname),
++        m_streamAnalyzer(0) {}
++    void setUp();
++    void tearDown();
++};
++
+ }
+ 
+ #endif
+--- a/tests/indextesters/indexsearchtester.cpp
++++ b/tests/indextesters/indexsearchtester.cpp
+@@ -27,6 +27,7 @@
+ #include "query.h"
+ #include "queryparser.h"
+ #include "unittestfunctions.h"
++#include "indexpluginloader.h"
+ 
+ #include  <errno.h>
+ #include <fstream>
+@@ -39,23 +40,12 @@
+ using namespace strigiunittest;
+ 
+ void
+-IndexSearchTester::setUp() {
++IndexSearchTest::setUp() {
++    IndexTest::setUp();
++
+     char buff[13];
+     char* dirname;
+     string separator;
+-    
+-    // generate index dir name
+-    strcpy(buff, "strigiXXXXXX");
+-    dirname = mkdtemp(buff);
+-    
+-    if (dirname) {
+-        cout << "created index dir: " << dirname << endl;
+-        indexdir.assign(dirname);
+-    } else {
+-        cerr << "Error creating temporary directory for index because of: "
+-            << strerror(errno) << endl;
+-        return;
+-    }
+ 
+     // generate indexed docs name
+     strcpy(buff, "strigiXXXXXX");
+@@ -68,7 +58,7 @@
+             << strerror(errno) << endl;
+         return;
+     }
+-    
++
+ #ifdef _WIN32
+     separator = "\\";
+ #else
+@@ -78,15 +68,15 @@
+     // prepare files to be indexed
+     string filename;
+     string filecontents;
+-    
++
+     filename = "testfile01";
+     filecontents = "this is a simple test file";
+     indexedFiles.insert(make_pair<string, string> (filename, filecontents));
+-    
++
+     filename = "testfile02";
+     filecontents = "unit testing example";
+     indexedFiles.insert(make_pair<string, string> (filename, filecontents));
+-    
++
+     // create files on file system
+     for (map<string,string>::iterator iter = indexedFiles.begin();
+             iter != indexedFiles.end(); iter++) {
+@@ -100,48 +90,37 @@
+             cerr << "error during creation of file " << fullpath << endl;
+         }
+     }
+-    
+-    manager = getIndexManager(backend, indexdir);
+ 
+-    CPPUNIT_ASSERT_MESSAGE ("manager == null", manager);
+-    
+     Strigi::AnalyzerConfiguration config;
+     Strigi::StreamAnalyzer* streamindexer = new Strigi::StreamAnalyzer(config);
+-    Strigi::IndexWriter* writer = manager->indexWriter();
+-    streamindexer->setIndexWriter(*writer);
+- 
++    streamindexer->setIndexWriter(*m_writer);
++
+     for (map<string,string>::iterator iter = indexedFiles.begin();
+          iter != indexedFiles.end(); iter++) {
+         string temp = filedir + separator + iter->first;
+         fprintf (stderr, "going to index %s\n", temp.c_str());
+         streamindexer->indexFile(temp);
+     }
+-    
++
+     delete streamindexer;
+-    
+-    writer->commit();
+-    
++
++    m_writer->commit();
+ }
+ 
+ void
+-IndexSearchTester::tearDown() {
+-    if (manager)
+-        delete manager;
+-    manager = NULL;
+-    
++IndexSearchTest::tearDown() {
+     // clean up data (does not work on windows)
+-    string cmd = "rm -r " + indexdir + " " + filedir;
++    string cmd = "rm -r '" + filedir + "'";
+     system(cmd.c_str());
++
++    IndexTest::tearDown();
+ }
+ 
+ void
+-IndexSearchTester::testVariables() {
+-    CPPUNIT_ASSERT_MESSAGE ("manager == NULL", manager);
+-    CPPUNIT_ASSERT_MESSAGE ("backend empty", !backend.empty());
+-    CPPUNIT_ASSERT_MESSAGE ("indexdir empty", !indexdir.empty());
++IndexSearchTest::testVariables() {
+     CPPUNIT_ASSERT_MESSAGE ("filedir empty", !filedir.empty());
+-    
+-    unsigned int indexedFilesSize = manager->indexReader()->countDocuments();
++
++    unsigned int indexedFilesSize = m_reader->countDocuments();
+     if (indexedFilesSize != indexedFiles.size()) {
+         ostringstream msg;
+         msg << "There are " << indexedFilesSize << " indexed files instead of "
+@@ -151,30 +130,24 @@
+ }
+ 
+ void
+-IndexSearchTester::testSystemLocationSearchIndexedFile() {
+-    Strigi::IndexReader* reader = manager->indexReader();
+-    CPPUNIT_ASSERT_MESSAGE("reader == NULL", reader);
+-    
++IndexSearchTest::testSystemLocationSearchIndexedFile() {
+     Strigi::QueryParser parser;
+ 
+     Strigi::Query query = parser.buildQuery("name:'testfile01'");
+-    vector<Strigi::IndexedDocument> matches = reader->query(query, 0, 10);
++    vector<Strigi::IndexedDocument> matches = m_reader->query(query, 0, 10);
+ 
+     int nhits = matches.size();
+-    CPPUNIT_ASSERT_EQUAL_MESSAGE("Number of hits is wrong.", nhits, 1);
++    CPPUNIT_ASSERT_EQUAL_MESSAGE("Number of hits is wrong.", 1, nhits);
+ }
+ 
+ void
+-IndexSearchTester::testSystemLocationSearchUnindexedFile() {
+-    Strigi::IndexReader* reader = manager->indexReader();
+-    CPPUNIT_ASSERT_MESSAGE("reader == NULL", reader);
+-
++IndexSearchTest::testSystemLocationSearchUnindexedFile() {
+     Strigi::QueryParser parser;
+ 
+     Strigi::Query query = parser.buildQuery(
+         Strigi::FieldRegister::pathFieldName+":'unindexed'");
+-    vector<Strigi::IndexedDocument> matches = reader->query(query, 0, 10);
++    vector<Strigi::IndexedDocument> matches = m_reader->query(query, 0, 10);
+     int nhits = matches.size();
+-    CPPUNIT_ASSERT_EQUAL_MESSAGE("Number of hits is wrong.", nhits, 0);
++    CPPUNIT_ASSERT_EQUAL_MESSAGE("Number of hits is wrong.", 0, nhits);
+ }
+ 
+--- a/tests/indextesters/indexsearchtester.h
++++ b/tests/indextesters/indexsearchtester.h
+@@ -20,42 +20,33 @@
+ #ifndef UNIT_TEST_INDEX_SEARCH_TESTER_H
+ #define UNIT_TEST_INDEX_SEARCH_TESTER_H
+ 
+-#include <cppunit/TestFixture.h>
+-#include <cppunit/extensions/HelperMacros.h>
++#include "indextest.h"
+ 
+ #include <map>
+-#include <string>
+ 
+-namespace Strigi
+-{
+-    class IndexManager;
+-}
++namespace strigiunittest {
++
++class IndexSearchTest : public IndexTest {
++private:
++    CPPUNIT_TEST_SUITE( IndexSearchTest );
++    CPPUNIT_TEST( testVariables );
++    CPPUNIT_TEST( testSystemLocationSearchIndexedFile );
++    CPPUNIT_TEST( testSystemLocationSearchUnindexedFile );
++    CPPUNIT_TEST_SUITE_END_ABSTRACT();
++
++    std::string filedir;
++    std::map<std::string,std::string> indexedFiles; //!< map with key = file name, and value = file contents
++
++    void testSystemLocationSearchIndexedFile();
++    void testSystemLocationSearchUnindexedFile();
++    void testVariables();
++
++public:
++    IndexSearchTest(const std::string& backendname) :IndexTest(backendname){}
++    void setUp();
++    void tearDown();
++};
+ 
+-namespace strigiunittest
+-{
+-    class IndexSearchTester : public CppUnit::TestFixture
+-    {
+-        CPPUNIT_TEST_SUITE( IndexSearchTester );
+-        CPPUNIT_TEST( testVariables );
+-        CPPUNIT_TEST( testSystemLocationSearchIndexedFile );
+-        CPPUNIT_TEST( testSystemLocationSearchUnindexedFile );
+-        CPPUNIT_TEST_SUITE_END_ABSTRACT();
+-        
+-        protected:
+-            Strigi::IndexManager* manager;
+-            std::string backend;
+-            std::string indexdir;
+-            std::string filedir;
+-            std::map<std::string,std::string> indexedFiles; //!< map with key = file name, and value = file contents
+-            
+-        public:
+-            virtual void setUp();
+-            virtual void tearDown();
+-            
+-            virtual void testSystemLocationSearchIndexedFile();
+-            virtual void testSystemLocationSearchUnindexedFile();
+-            virtual void testVariables();
+-    };
+ }
+ 
+ #endif
+--- /dev/null
++++ b/tests/indextesters/indextest.cpp
+@@ -0,0 +1,52 @@
++/* This file is part of Strigi Desktop Search
++ *
++ * Copyright (C) 2007 Jos van den Oever <jos at vandenoever.info>
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public License
++ * along with this library; see the file COPYING.LIB.  If not, write to
++ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
++ * Boston, MA 02110-1301, USA.
++ */
++#include "indextest.h"
++#include "indexmanager.h"
++#include "indexpluginloader.h"
++
++using namespace std;
++using namespace Strigi;
++using namespace strigiunittest;
++
++IndexTest::IndexTest(const string& backendname, const string& indexpath)
++    :m_backendname(backendname), m_indexpath(":memory:"), m_manager(0) {
++}
++
++void
++IndexTest::setUp() {
++    m_manager = IndexPluginLoader::createIndexManager(
++        m_backendname.c_str(), m_indexpath.c_str());
++    CPPUNIT_ASSERT_MESSAGE("manager creation failed", m_manager);
++    if (!m_manager) return;
++
++    m_writer = m_manager->indexWriter();
++    CPPUNIT_ASSERT_MESSAGE("writer creation failed", m_writer);
++
++    m_reader = m_manager->indexReader();
++    CPPUNIT_ASSERT_MESSAGE("reader creation failed", m_reader);
++}
++
++void
++IndexTest::tearDown() {
++    IndexPluginLoader::deleteIndexManager(m_manager);
++    // clean up data (if any)
++    string cmd("rm -rf '" + m_indexpath + "'");
++    system(cmd.c_str());
++}
+--- /dev/null
++++ b/tests/indextesters/indextest.h
+@@ -0,0 +1,51 @@
++/* This file is part of Strigi Desktop Search
++ *
++ * Copyright (C) 2007 Jos van den Oever <jos at vandenoever.info>
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public License
++ * along with this library; see the file COPYING.LIB.  If not, write to
++ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
++ * Boston, MA 02110-1301, USA.
++ */
++#ifndef UNIT_TEST_INDEX_TEST_H
++#define UNIT_TEST_INDEX_TEST_H
++
++#include <cppunit/TestFixture.h>
++#include <cppunit/extensions/HelperMacros.h>
++#include <string>
++
++namespace Strigi {
++    class IndexManager;
++    class IndexWriter;
++    class IndexReader;
++}
++
++namespace strigiunittest {
++
++class IndexTest : public CppUnit::TestFixture {
++protected:
++    const std::string m_backendname;
++    const std::string m_indexpath;
++    Strigi::IndexManager* m_manager;
++    Strigi::IndexReader* m_reader;
++    Strigi::IndexWriter* m_writer;
++
++    IndexTest(const std::string& backendname,
++        const std::string& indexpath = ":memory:");
++    void setUp();
++    void tearDown();
++};
++
++}
++
++#endif
+--- a/tests/indextesters/indexwritertester.cpp
++++ b/tests/indextesters/indexwritertester.cpp
+@@ -20,55 +20,32 @@
+ #include "indexwritertester.h"
+ 
+ #include "analysisresult.h"
+-#include "analyzerconfiguration.h"
+-#include "indexmanager.h"
+ #include "indexwriter.h"
+ #include "indexreader.h"
+ #include "fieldtypes.h"
+-#include "analyzerconfiguration.h"
+ #include "query.h"
+ #include "queryparser.h"
+ 
+-#include <string>
+ #include <sstream>
+-#include <sys/stat.h>
+-#include <sys/types.h>
+-#include <stdlib.h>
+-#ifdef _WIN32
+-#include <direct.h>
+-#endif
+ 
+ using namespace std;
+ using namespace strigiunittest;
+ using namespace Strigi;
+ 
+-void IndexWriterTester::setUp()
+-{
+-    m_manager = createManager();
+-    m_writer = m_manager->indexWriter();
+-    m_reader = m_manager->indexReader();
+-
+-    CPPUNIT_ASSERT_MESSAGE("writer creation failed", m_writer);
+-    CPPUNIT_ASSERT_MESSAGE("reader creation failed", m_reader);
+-
+-    m_streamAnalyzer = new Strigi::StreamAnalyzer( m_analyzerConfiguration );
++void
++IndexWriterTest::setUp() {
++    IndexTest::setUp();
++    m_streamAnalyzer = new StreamAnalyzer( m_analyzerConfiguration );
+ }
+ 
+-void IndexWriterTester::tearDown()
+-{
++void
++IndexWriterTest::tearDown() {
+     delete m_streamAnalyzer;
+-    deleteManager( m_manager );
+-}
+-
+-
+-void IndexWriterTester::deleteManager( Strigi::IndexManager* m )
+-{
+-    delete m;
++    IndexTest::tearDown();
+ }
+ 
+-
+-void IndexWriterTester::testAddText()
+-{
++void
++IndexWriterTest::testAddText() {
+     // test adding very simple text
+     string path( "/tmp/dummy.txt" );
+     {
+@@ -78,9 +55,12 @@
+     }
+     m_writer->commit();
+ 
+-    std::vector<IndexedDocument> results = m_reader->query( QueryParser::buildQuery("dummy"), 0, 100 );
+-    CPPUNIT_ASSERT_EQUAL_MESSAGE( "got invalid number of results", 1, ( int )results.size() );
+-    CPPUNIT_ASSERT_EQUAL_MESSAGE( "got invalid path result", path, results[0].uri );
++    std::vector<IndexedDocument> results = m_reader->query(
++        QueryParser::buildQuery("dummy"), 0, 100 );
++    CPPUNIT_ASSERT_EQUAL_MESSAGE( "got invalid number of results", 1,
++        (int)results.size() );
++    CPPUNIT_ASSERT_EQUAL_MESSAGE( "got invalid path result", path,
++        results[0].uri );
+ 
+     m_writer->deleteAllEntries();
+ 
+@@ -88,9 +68,8 @@
+ 
+ }
+ 
+-
+-void IndexWriterTester::testDeleteAllEntries()
+-{
++void
++IndexWriterTest::testDeleteAllEntries() {
+     // add some random data
+     string path( "/tmp/dummy.txt" );
+     {
+@@ -107,18 +86,23 @@
+     // now make sure nothing is left
+     std::map<std::string, time_t> children;
+     m_reader->getChildren( std::string(), children );
+-    CPPUNIT_ASSERT_MESSAGE( "Still files left after calling deleteAllEntries.", children.empty() );
++    CPPUNIT_ASSERT_MESSAGE( "Still files left after calling deleteAllEntries.",
++        children.empty() );
+ 
+-    std::vector<IndexedDocument> results = m_reader->query( QueryParser::buildQuery( FieldRegister::pathFieldName + "=\"" + path + "\"" ), 0, 100 );
+-    CPPUNIT_ASSERT_MESSAGE( "Query results not empty after deleteAllEntries", results.empty() );
+-
+-    results = m_reader->query( QueryParser::buildQuery( FieldRegister::filenameFieldName + "=\"dummy.txt\"" ), 0, 100 );
+-    CPPUNIT_ASSERT_MESSAGE( "Query results not empty after deleteAllEntries", results.empty() );
++    std::vector<IndexedDocument> results = m_reader->query(
++        QueryParser::buildQuery(
++            FieldRegister::pathFieldName + "=\"" + path + "\"" ), 0, 100 );
++    CPPUNIT_ASSERT_MESSAGE( "Query results not empty after deleteAllEntries",
++       results.empty() );
++
++    results = m_reader->query( QueryParser::buildQuery(
++        FieldRegister::filenameFieldName + "=\"dummy.txt\"" ), 0, 100 );
++    CPPUNIT_ASSERT_MESSAGE( "Query results not empty after deleteAllEntries",
++        results.empty() );
+ }
+ 
+-
+-void IndexWriterTester::testDeleteEntries()
+-{
++void
++IndexWriterTest::testDeleteEntries() {
+     // add some random data
+     string path1( "/tmp/dummy1.txt" );
+     string path2( "/tmp/dummy2.txt" );
+@@ -128,11 +112,11 @@
+         AnalysisResult anaRes1( path1, 1, *m_writer, *m_streamAnalyzer );
+         AnalysisResult anaRes2( path2, 1, *m_writer, *m_streamAnalyzer );
+ 
+-        m_writer->addValue( &anaRes1, m_fieldRegister.pathField, anaRes1.path() );
+-        m_writer->addValue( &anaRes1, m_fieldRegister.filenameField, filename1 );
++        m_writer->addValue(&anaRes1, m_fieldRegister.pathField, anaRes1.path());
++        m_writer->addValue(&anaRes1, m_fieldRegister.filenameField, filename1);
+ 
+-        m_writer->addValue( &anaRes2, m_fieldRegister.pathField, anaRes2.path() );
+-        m_writer->addValue( &anaRes2, m_fieldRegister.filenameField, filename2 );
++        m_writer->addValue(&anaRes2, m_fieldRegister.pathField, anaRes2.path());
++        m_writer->addValue(&anaRes2, m_fieldRegister.filenameField, filename2 );
+     }
+     m_writer->commit();
+ 
+--- a/tests/indextesters/indexwritertester.h
++++ b/tests/indextesters/indexwritertester.h
+@@ -20,56 +20,40 @@
+ #ifndef UNIT_TEST_INDEX_WRITER_TESTER_H
+ #define UNIT_TEST_INDEX_WRITER_TESTER_H
+ 
+-#include <cppunit/TestFixture.h>
+-#include <cppunit/extensions/HelperMacros.h>
+-#include <string>
++#include "indextest.h"
+ 
+ #include "analyzerconfiguration.h"
+ #include "fieldtypes.h"
+ 
+ namespace Strigi {
+-    class IndexManager;
+-    class IndexWriter;
+-    class IndexReader;
+     class StreamAnalyzer;
+     class AnalysisResult;
+ }
+ 
+-namespace strigiunittest
+-{
+-    class IndexWriterTester : public CppUnit::TestFixture
+-    {
+-        CPPUNIT_TEST_SUITE( IndexWriterTester );
+-        CPPUNIT_TEST( testAddText );
+-        CPPUNIT_TEST( testDeleteAllEntries );
+-
+-        CPPUNIT_TEST_SUITE_END_ABSTRACT();
+-
+-    private:
+-	Strigi::IndexManager* m_manager;
+-
+-	Strigi::IndexWriter* m_writer;
+-	Strigi::IndexReader* m_reader;
+-	Strigi::StreamAnalyzer* m_streamAnalyzer;
+-	Strigi::AnalyzerConfiguration m_analyzerConfiguration;
+-	Strigi::FieldRegister m_fieldRegister;
+-
+-    protected:
+-	virtual Strigi::IndexManager* createManager() = 0;
+-	/**
+-	 * delete the manager. The default implementation simply
+-	 * calls delete.
+-	 */
+-	virtual void deleteManager( Strigi::IndexManager* );
+-                
+-    public:
+-	virtual void setUp();
+-	virtual void tearDown();
+-
+-	void testAddText();
+-	void testDeleteAllEntries();
+-	void testDeleteEntries();
+-    };
++namespace strigiunittest {
++
++class IndexWriterTest : public IndexTest {
++private:
++    CPPUNIT_TEST_SUITE( IndexWriterTest );
++    CPPUNIT_TEST( testAddText );
++    CPPUNIT_TEST( testDeleteAllEntries );
++    CPPUNIT_TEST_SUITE_END_ABSTRACT();
++
++    Strigi::StreamAnalyzer* m_streamAnalyzer;
++    Strigi::AnalyzerConfiguration m_analyzerConfiguration;
++    Strigi::FieldRegister m_fieldRegister;
++
++    void testAddText();
++    void testDeleteAllEntries();
++    void testDeleteEntries();
++
++public:
++    IndexWriterTest(const std::string& backendname) :IndexTest(backendname),
++        m_streamAnalyzer(0) {}
++    void setUp();
++    void tearDown();
++};
++
+ }
+ 
+ #endif
+--- /dev/null
++++ b/tests/indextesters/sqlitetests.cpp
+@@ -0,0 +1,52 @@
++/* This file is part of Strigi Desktop Search
++ *
++ * Copyright (C) 2007 Jos van den Oever <jos at vandenoever.info>
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public License
++ * along with this library; see the file COPYING.LIB.  If not, write to
++ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
++ * Boston, MA 02110-1301, USA.
++ */
++
++#include "indexreadertester.h"
++#include "indexwritertester.h"
++#include "indexsearchtester.h"
++using namespace strigiunittest;
++/*
++class SQLiteIndexReaderTest : public IndexReaderTest {
++private:
++    CPPUNIT_TEST_SUB_SUITE( SQLiteIndexReaderTest, IndexReaderTest);
++    CPPUNIT_TEST_SUITE_END();
++public:
++    SQLiteIndexReaderTest() :IndexReaderTest("sqlite") {}
++};
++CPPUNIT_TEST_SUITE_REGISTRATION( SQLiteIndexReaderTest );
++*/
++class SQLiteIndexWriterTest : public IndexWriterTest {
++private:
++    CPPUNIT_TEST_SUB_SUITE( SQLiteIndexWriterTest, IndexWriterTest);
++    CPPUNIT_TEST_SUITE_END();
++public:
++    SQLiteIndexWriterTest() :IndexWriterTest("sqlite") {}
++};
++CPPUNIT_TEST_SUITE_REGISTRATION( SQLiteIndexWriterTest );
++/*
++
++class SQLiteIndexSearchTest : public IndexSearchTest {
++private:
++    CPPUNIT_TEST_SUB_SUITE( SQLiteIndexSearchTest, IndexSearchTest);
++    CPPUNIT_TEST_SUITE_END();
++public:
++    SQLiteIndexSearchTest() :IndexSearchTest("sqlite") {}
++};
++CPPUNIT_TEST_SUITE_REGISTRATION( SQLiteIndexSearchTest );*/
+--- a/tests/luceneindexer/CMakeLists.txt
++++ /dev/null
+@@ -1,33 +0,0 @@
+-STRING(REGEX REPLACE /test /src INC_DIR ${CMAKE_CURRENT_SOURCE_DIR})
+-
+-if (ENABLE_LOG4CXX AND Log4cxx_FOUND)
+-    set(lucenetest_LIBS ${lucenetest_LIBS} ${LOG4CXX_LIBRARIES})
+-    set (INC_DIR ${INC_DIR} ${LOG4CXX_INCLUDE_DIR})
+-    add_definitions(-DHAVE_LOG4CXX)
+-endif (ENABLE_LOG4CXX AND Log4cxx_FOUND)
+-
+-include_directories (. .. ${INC_DIR}
+-                     ../indextesters
+-                     ../streamanalyzer
+-                     ${strigi_SOURCE_DIR}/src/streamanalyzer
+-                     ${strigi_SOURCE_DIR}/src/luceneindexer
+-                     ${strigi_SOURCE_DIR}/src/streams
+-                     ${strigi_BINARY_DIR}/src/streams
+-                     ${strigi_SOURCE_DIR}/src/streams/strigi
+-                     ${CLUCENE_INCLUDE_DIR}
+-)
+-
+-add_executable (lucenetest  luceneindexmanagertest.cpp
+-                            luceneindexreadertest.cpp
+-                            luceneindexwritertest.cpp
+-                            luceneindexsearchtest.cpp
+-                            lucenediranalyzertest.cpp
+-)
+-
+-target_link_libraries (lucenetest   test_runner
+-                                    streamanalyzertesters
+-                                    indextesters
+-                                    cluceneindex
+-                                    ${lucenetest_LIBS})
+-
+-add_test (lucenetests lucenetest)
+--- a/tests/luceneindexer/lucenediranalyzertest.cpp
++++ /dev/null
+@@ -1,37 +0,0 @@
+-/* This file is part of Strigi Desktop Search
+- *
+- * Copyright (C) 2007 Flavio Castelli <flavio.castelli at gmail.com>
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Library General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * Library General Public License for more details.
+- *
+- * You should have received a copy of the GNU Library General Public License
+- * along with this library; see the file COPYING.LIB.  If not, write to
+- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+- * Boston, MA 02110-1301, USA.
+- */
+-#include "lucenediranalyzertest.h"
+-
+-using namespace std;
+-using namespace strigiunittest;
+-
+-// Registers the fixture into the 'registry'
+-CPPUNIT_TEST_SUITE_REGISTRATION( LuceneDirAnalyzerTest );
+-
+-void LuceneDirAnalyzerTest::setUp()
+-{
+-    backend = "clucene";
+-    DirAnalyzerTester::setUp();
+-}
+-
+-void LuceneDirAnalyzerTest::tearDown()
+-{
+-    DirAnalyzerTester::tearDown();
+-}
+--- a/tests/luceneindexer/lucenediranalyzertest.h
++++ /dev/null
+@@ -1,40 +0,0 @@
+-/* This file is part of Strigi Desktop Search
+- *
+- * Copyright (C) 2007 Flavio Castelli <flavio.castelli at gmail.com>
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Library General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * Library General Public License for more details.
+- *
+- * You should have received a copy of the GNU Library General Public License
+- * along with this library; see the file COPYING.LIB.  If not, write to
+- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+- * Boston, MA 02110-1301, USA.
+- */
+-#ifndef UNIT_TEST_LUCENE_SEARCH_TEST_H
+-#define UNIT_TEST_LUCENE_SEARCH_TEST_H
+-
+-#include "diranalyzertester.h"
+-
+-namespace strigiunittest
+-{
+-    class LuceneDirAnalyzerTest : public DirAnalyzerTester
+-    {
+-        CPPUNIT_TEST_SUB_SUITE( LuceneDirAnalyzerTest,  DirAnalyzerTester);
+-        CPPUNIT_TEST( testVariables );
+-        CPPUNIT_TEST( testCreateIndex );
+-        CPPUNIT_TEST_SUITE_END();
+-        
+-        public:
+-            void setUp();
+-            void tearDown();
+-    };
+-}
+-
+-#endif
+--- a/tests/luceneindexer/luceneindexmanagertest.cpp
++++ /dev/null
+@@ -1,62 +0,0 @@
+-/* This file is part of Strigi Desktop Search
+- *
+- * Copyright (C) 2007 Flavio Castelli <flavio.castelli at gmail.com>
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Library General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * Library General Public License for more details.
+- *
+- * You should have received a copy of the GNU Library General Public License
+- * along with this library; see the file COPYING.LIB.  If not, write to
+- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+- * Boston, MA 02110-1301, USA.
+- */
+-#include "luceneindexmanagertest.h"
+-
+-#include "analysisresult.h"
+-#include "analyzerconfiguration.h"
+-#include "cluceneindexmanager.h"
+-#include "indexwriter.h"
+-#include "indexreader.h"
+-#include "query.h"
+-
+-#include <sys/stat.h>
+-#include <sys/types.h>
+-#include <stdlib.h>
+-#ifdef _WIN32
+-#include <direct.h>
+-#endif
+-
+-using namespace std;
+-using namespace strigiunittest;
+-
+-// Registers the fixture into the 'registry'
+-CPPUNIT_TEST_SUITE_REGISTRATION( LuceneIndexManagerTest );
+-
+-Strigi::IndexManager* LuceneIndexManagerTest::createManager()
+-{
+-    string path = "testcluceneindex";
+-
+-    // initialize a directory for writing and an indexmanager
+-#ifdef _WIN32
+-    mkdir(path.c_str());
+-#else
+-    mkdir(path.c_str(), S_IRUSR|S_IWUSR|S_IXUSR);
+-#endif
+-
+-    return createCLuceneIndexManager(path.c_str());
+-}
+-
+-void LuceneIndexManagerTest::deleteManager( Strigi::IndexManager* m )
+-{
+-    delete m;
+-
+-    // clean up data
+-    system("rm -r testcluceneindex");
+-}
+--- a/tests/luceneindexer/luceneindexmanagertest.h
++++ /dev/null
+@@ -1,38 +0,0 @@
+-/* This file is part of Strigi Desktop Search
+- *
+- * Copyright (C) 2007 Flavio Castelli <flavio.castelli at gmail.com>
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Library General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * Library General Public License for more details.
+- *
+- * You should have received a copy of the GNU Library General Public License
+- * along with this library; see the file COPYING.LIB.  If not, write to
+- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+- * Boston, MA 02110-1301, USA.
+- */
+-#ifndef UNIT_TEST_LUCENE_INDEX_MANAGER_TEST_H
+-#define UNIT_TEST_LUCENE_INDEX_MANAGER_TEST_H
+-
+-#include "indexmanagertester.h"
+-
+-namespace strigiunittest
+-{
+-    class LuceneIndexManagerTest : public IndexManagerTester
+-    {
+-        CPPUNIT_TEST_SUB_SUITE( LuceneIndexManagerTest, IndexManagerTester);
+-        CPPUNIT_TEST_SUITE_END();
+-
+-    private:
+-	Strigi::IndexManager* createManager();
+-	void deleteManager( Strigi::IndexManager* );
+-    };
+-}
+-
+-#endif
+--- a/tests/luceneindexer/luceneindexreadertest.cpp
++++ /dev/null
+@@ -1,64 +0,0 @@
+-/* This file is part of Strigi Desktop Search
+- *
+- * Copyright (C) 2007 Flavio Castelli <flavio.castelli at gmail.com>
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Library General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * Library General Public License for more details.
+- *
+- * You should have received a copy of the GNU Library General Public License
+- * along with this library; see the file COPYING.LIB.  If not, write to
+- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+- * Boston, MA 02110-1301, USA.
+- */
+-#include "luceneindexreadertest.h"
+-
+-#include "analysisresult.h"
+-#include "analyzerconfiguration.h"
+-#include "cluceneindexmanager.h"
+-#include "indexwriter.h"
+-#include "indexreader.h"
+-#include "query.h"
+-
+-#include <string>
+-#include <sstream>
+-#include <sys/stat.h>
+-#include <sys/types.h>
+-#include <stdlib.h>
+-#ifdef _WIN32
+-#include <direct.h>
+-#endif
+-
+-using namespace std;
+-using namespace strigiunittest;
+-
+-// Registers the fixture into the 'registry'
+-CPPUNIT_TEST_SUITE_REGISTRATION( LuceneIndexReaderTest );
+-
+-Strigi::IndexManager* LuceneIndexReaderTest::createManager()
+-{
+-    string path = "testcluceneindex";
+-
+-    // initialize a directory for writing and an indexmanager
+-#ifdef _WIN32
+-    mkdir(path.c_str());
+-#else
+-    mkdir(path.c_str(), S_IRUSR|S_IWUSR|S_IXUSR);
+-#endif
+-
+-    return createCLuceneIndexManager(path.c_str());
+-}
+-
+-void LuceneIndexReaderTest::deleteManager( Strigi::IndexManager* m )
+-{
+-    delete m;
+-
+-    // clean up data
+-    system("rm -r testcluceneindex");
+-}
+--- a/tests/luceneindexer/luceneindexreadertest.h
++++ /dev/null
+@@ -1,38 +0,0 @@
+-/* This file is part of Strigi Desktop Search
+- *
+- * Copyright (C) 2007 Flavio Castelli <flavio.castelli at gmail.com>
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Library General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * Library General Public License for more details.
+- *
+- * You should have received a copy of the GNU Library General Public License
+- * along with this library; see the file COPYING.LIB.  If not, write to
+- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+- * Boston, MA 02110-1301, USA.
+- */
+-#ifndef UNIT_TEST_LUCENE_INDEX_READER_TEST_H
+-#define UNIT_TEST_LUCENE_INDEX_READER_TEST_H
+-
+-#include "indexreadertester.h"
+-
+-namespace strigiunittest
+-{
+-    class LuceneIndexReaderTest : public IndexReaderTester
+-    {
+-        CPPUNIT_TEST_SUB_SUITE( LuceneIndexReaderTest,  IndexReaderTester);
+-        CPPUNIT_TEST_SUITE_END();
+-        
+-    private:
+-	Strigi::IndexManager* createManager();
+-	void deleteManager( Strigi::IndexManager* );
+-    };
+-}
+-
+-#endif
+--- a/tests/luceneindexer/luceneindexsearchtest.cpp
++++ /dev/null
+@@ -1,37 +0,0 @@
+-/* This file is part of Strigi Desktop Search
+- *
+- * Copyright (C) 2007 Flavio Castelli <flavio.castelli at gmail.com>
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Library General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * Library General Public License for more details.
+- *
+- * You should have received a copy of the GNU Library General Public License
+- * along with this library; see the file COPYING.LIB.  If not, write to
+- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+- * Boston, MA 02110-1301, USA.
+- */
+-#include "luceneindexsearchtest.h"
+-
+-using namespace std;
+-using namespace strigiunittest;
+-
+-// Registers the fixture into the 'registry'
+-CPPUNIT_TEST_SUITE_REGISTRATION( LuceneIndexSearchTest );
+-
+-void LuceneIndexSearchTest::setUp()
+-{
+-    backend = "clucene";
+-    IndexSearchTester::setUp();
+-}
+-
+-void LuceneIndexSearchTest::tearDown()
+-{
+-    IndexSearchTester::tearDown();
+-}
+--- a/tests/luceneindexer/luceneindexsearchtest.h
++++ /dev/null
+@@ -1,41 +0,0 @@
+-/* This file is part of Strigi Desktop Search
+- *
+- * Copyright (C) 2007 Flavio Castelli <flavio.castelli at gmail.com>
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Library General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * Library General Public License for more details.
+- *
+- * You should have received a copy of the GNU Library General Public License
+- * along with this library; see the file COPYING.LIB.  If not, write to
+- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+- * Boston, MA 02110-1301, USA.
+- */
+-#ifndef UNIT_TEST_LUCENE_SEARCH_TEST_H
+-#define UNIT_TEST_LUCENE_SEARCH_TEST_H
+-
+-#include "indexsearchtester.h"
+-
+-namespace strigiunittest
+-{
+-    class LuceneIndexSearchTest : public IndexSearchTester
+-    {
+-        CPPUNIT_TEST_SUB_SUITE( LuceneIndexSearchTest,  IndexSearchTester);
+-        CPPUNIT_TEST( testVariables );
+-        CPPUNIT_TEST( testSystemLocationSearchIndexedFile );
+-        CPPUNIT_TEST( testSystemLocationSearchUnindexedFile );
+-        CPPUNIT_TEST_SUITE_END();
+-        
+-        public:
+-            void setUp();
+-            void tearDown();
+-    };
+-}
+-
+-#endif
+--- a/tests/luceneindexer/luceneindexwritertest.cpp
++++ /dev/null
+@@ -1,63 +0,0 @@
+-/* This file is part of Strigi Desktop Search
+- *
+- * Copyright (C) 2007 Flavio Castelli <flavio.castelli at gmail.com>
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Library General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * Library General Public License for more details.
+- *
+- * You should have received a copy of the GNU Library General Public License
+- * along with this library; see the file COPYING.LIB.  If not, write to
+- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+- * Boston, MA 02110-1301, USA.
+- */
+-#include "luceneindexwritertest.h"
+-
+-#include "analysisresult.h"
+-#include "analyzerconfiguration.h"
+-#include "cluceneindexmanager.h"
+-#include "indexwriter.h"
+-#include "query.h"
+-
+-#include <string>
+-#include <sstream>
+-#include <sys/stat.h>
+-#include <sys/types.h>
+-#include <stdlib.h>
+-#ifdef _WIN32
+-#include <direct.h>
+-#endif
+-
+-using namespace std;
+-using namespace strigiunittest;
+-
+-// Registers the fixture into the 'registry'
+-CPPUNIT_TEST_SUITE_REGISTRATION( LuceneIndexWriterTest );
+-
+-Strigi::IndexManager* LuceneIndexWriterTest::createManager()
+-{
+-    string path = "testcluceneindex";
+-
+-    // initialize a directory for writing and an indexmanager
+-#ifdef _WIN32
+-    mkdir(path.c_str());
+-#else
+-    mkdir(path.c_str(), S_IRUSR|S_IWUSR|S_IXUSR);
+-#endif
+-
+-    return createCLuceneIndexManager(path.c_str());
+-}
+-
+-void LuceneIndexWriterTest::deleteManager( Strigi::IndexManager* m )
+-{
+-    delete m;
+-
+-    // clean up data
+-    system("rm -r testcluceneindex");
+-}
+--- a/tests/luceneindexer/luceneindexwritertest.h
++++ /dev/null
+@@ -1,38 +0,0 @@
+-/* This file is part of Strigi Desktop Search
+- *
+- * Copyright (C) 2007 Flavio Castelli <flavio.castelli at gmail.com>
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Library General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * Library General Public License for more details.
+- *
+- * You should have received a copy of the GNU Library General Public License
+- * along with this library; see the file COPYING.LIB.  If not, write to
+- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+- * Boston, MA 02110-1301, USA.
+- */
+-#ifndef UNIT_TEST_LUCENE_INDEX_WRITER_TEST_H
+-#define UNIT_TEST_LUCENE_INDEX_WRITER_TEST_H
+-
+-#include "indexwritertester.h"
+-
+-namespace strigiunittest
+-{
+-    class LuceneIndexWriterTest : public IndexWriterTester
+-    {
+-        CPPUNIT_TEST_SUB_SUITE( LuceneIndexWriterTest, IndexWriterTester);
+-        CPPUNIT_TEST_SUITE_END();
+-        
+-    private:
+-	Strigi::IndexManager* createManager();
+-	void deleteManager( Strigi::IndexManager* );
+-    };
+-}
+-
+-#endif
+--- a/tests/streamanalyzer/diranalyzertester.cpp
++++ b/tests/streamanalyzer/diranalyzertester.cpp
+@@ -23,6 +23,7 @@
+ #include "diranalyzer.h"
+ #include "indexmanager.h"
+ #include "indexreader.h"
++#include "indexpluginloader.h"
+ #include "unittestfunctions.h"
+ 
+ #include <errno.h>
+@@ -105,8 +106,9 @@
+ 
+ void DirAnalyzerTester::tearDown()
+ {
+-    if (manager)
+-        delete manager;
++    if (manager) {
++        Strigi::IndexPluginLoader::deleteIndexManager(manager);
++    }
+     manager = NULL;
+ 
+     // clean up data
+--- a/tests/test_runner.cpp
++++ b/tests/test_runner.cpp
+@@ -24,11 +24,27 @@
+ #include <cppunit/TextTestRunner.h>
+ 
+ #include "strigilogging.h"
++#include "config.h"
++
++#include <iostream>
++using namespace std;
++
++int main() {
++    // set some environment variables so that the system can find the desired
++    // files
++    setenv("XDG_DATA_HOME",
++        SOURCEDIR"/src/streamanalyzer/fieldproperties", 1);
++    setenv("XDG_DATA_DIRS",
++        SOURCEDIR"/src/streamanalyzer/fieldproperties", 1);
++    setenv("STRIGI_PLUGIN_PATH",
++        BINARYDIR"/src/luceneindexer/:"
++        BINARYDIR"/src/estraierindexer:"
++        BINARYDIR"/src/sqliteindexer", 1);
++
++cerr << BINARYDIR << endl;
+ 
+-int main()
+-{
+     STRIGI_LOG_INIT_BASIC()
+-    
++
+     // Get the top level suite from the registry
+     CppUnit::Test *suite = CppUnit::TestFactoryRegistry::getRegistry().makeTest();
+ 
+@@ -46,18 +62,3 @@
+     return wasSucessful ? 0 : 1;
+ }
+ 
+-// using namespace CppUnit;
+-// 
+-// int main (int argc, char* argv[]) {
+-//     TextTestRunner runner;
+-//     TestFactoryRegistry& registry = TestFactoryRegistry::getRegistry();
+-// 
+-//      // run all tests if none specified on command line
+-//     Test* test_to_run = registry.makeTest();
+-//     if (argc>1)
+-//         test_to_run = test_to_run->findTest(argv[1]);
+-// 
+-//     runner.addTest( test_to_run );
+-//     bool failed = runner.run("", false);
+-//     return !failed;
+-// }
+--- a/tests/utils/CMakeLists.txt
++++ b/tests/utils/CMakeLists.txt
+@@ -1,8 +1,9 @@
+ include_directories (   .
++                        ${strigi_BINARY_DIR}/src/streams
+                         ${strigi_SOURCE_DIR}/src/streamanalyzer
+                         ${strigi_SOURCE_DIR}/src/combinedindexer
+                     )
+ 
+ add_library(unittestfunctions unittestfunctions.cpp)
+ 
+-target_link_libraries (unittestfunctions combinedindex)
+\ No newline at end of file
++target_link_libraries (unittestfunctions combinedindex)
+--- a/tests/utils/unittestfunctions.cpp
++++ b/tests/utils/unittestfunctions.cpp
+@@ -21,22 +21,14 @@
+ #include "unittestfunctions.h"
+ 
+ #include "indexmanager.h"
+-#include "combinedindexmanager.h"
++#include "indexpluginloader.h"
+ #include <vector>
+ #include <algorithm>
+ 
+ using namespace std;
+ 
+ Strigi::IndexManager* strigiunittest::getIndexManager(string& backend,
+-                                                      const string& indexdir)
+-{
+-    // check arguments: backend
+-    const vector<string>& backends = CombinedIndexManager::backEnds();
+-
+-    vector<string>::const_iterator b
+-            = find(backends.begin(), backends.end(), backend);
+-    if (b == backends.end())
+-        return 0;
+-
+-    return CombinedIndexManager::factories()[backend](indexdir.c_str());
++                                                      const string& indexdir) {
++    return Strigi::IndexPluginLoader::createIndexManager(backend.c_str(),
++        indexdir.c_str());
+ }

Added: kde-extras/strigi/trunk/debian/patches/01_strigi_branch_r727526.diff
===================================================================
--- kde-extras/strigi/trunk/debian/patches/01_strigi_branch_r727526.diff	                        (rev 0)
+++ kde-extras/strigi/trunk/debian/patches/01_strigi_branch_r727526.diff	2007-10-28 14:05:27 UTC (rev 7694)
@@ -0,0 +1,4864 @@
+--- a/cmake/FindCppUnit.cmake
++++ b/cmake/FindCppUnit.cmake
+@@ -7,7 +7,9 @@
+ 
+ include (MacroEnsureVersion)
+ 
+-SET(CPPUNIT_MIN_VERSION 1.12.0)
++if(NOT CPPUNIT_MIN_VERSION)
++  SET(CPPUNIT_MIN_VERSION 1.12.0)
++endif(NOT CPPUNIT_MIN_VERSION)
+ 
+ FIND_PROGRAM(CPPUNIT_CONFIG_EXECUTABLE cppunit-config )
+ 
+--- a/cmake/FindHyperEstraier.cmake
++++ b/cmake/FindHyperEstraier.cmake
+@@ -8,7 +8,7 @@
+ #
+ 
+ # find estconfig executable
+-FIND_PROGRAM(ESTCONFIG NAMES estconfig PATHS /bin /usr/bin /usr/local/bin )
++FIND_PROGRAM(ESTCONFIG NAMES estconfig PATHS /bin )
+ 
+ # get configuration options
+ IF (ESTCONFIG)
+--- a/config.h.cmake
++++ b/config.h.cmake
+@@ -147,7 +147,34 @@
+ 
+ #define LIBINSTALLDIR "${LIBINSTALLDIR}"
+ 
++#define SOURCEDIR "${CMAKE_SOURCE_DIR}"
++
++#define BINARYDIR "${CMAKE_BINARY_DIR}"
++
+ #define INSTALLDIR "${CMAKE_INSTALL_PREFIX}"
+ 
+ #define MIMEINSTALLDIR "${MIMEINSTALLDIR}"
++
++// Definition of types that are used internally
++
++#if !@HAVE_INTPTR_T@
++ typedef int intptr_t;
++ #define HAVE_INTPTR_T 1
++#endif
++
++#if !@HAVE_SOCKLEN_T@
++ typedef int socklen_t;
++ #define HAVE_SOCKLEN_T 1
++#endif
++
++#if !@HAVE_SSIZE_T@
++ #ifndef _SSIZE_T_DEFINED 
++  #ifndef HAVE_SSIZE_T
++   typedef signed int ssize_t;
++   #define HAVE_SSIZE_T 1
++  #endif
++  #define _SSIZE_T_DEFINED 1    // kdewin32 define
++ #endif
++#endif
++
+ #endif //CONFIG_H
+--- a/src/CMakeLists.txt
++++ b/src/CMakeLists.txt
+@@ -2,7 +2,6 @@
+ # Check copied from kdelibs FindX11.cmake.
+ CHECK_LIBRARY_EXISTS("socket" "connect" "" CMAKE_LIB_SOCKET_HAS_CONNECT)
+ 
+-
+ set(DIRS streams streamanalyzer archivereader xsd dummyindexer xmlindexer combinedindexer indexertests strigicmd)
+ 
+ if (CLucene_FOUND)
+@@ -11,32 +10,31 @@
+ 
+ if (HyperEstraier_FOUND)
+   set(DIRS ${DIRS} estraierindexer)
+-  message("** HyperEstraier support is experimental. **")
++  message("** HyperEstraier support is broken. Do not rely on it. **")
+ endif (HyperEstraier_FOUND)
+ 
+ if (SQLite_FOUND)
+   set(DIRS ${DIRS} sqliteindexer)
+-  message("** SQLite support is experimental. **")
++  message("** SQLite support is broken. Do not rely on it. **")
+ endif (SQLite_FOUND)
+ 
+-if (CLucene_FOUND OR HyperEstraier_FOUND OR SQLite_FOUND)
+-  if(NOT WIN32)
+-     set(DIRS ${DIRS} htmlgui)
+-  endif(NOT WIN32)
+-  # searchclient needs htmlgui which is not compilable on win32
+-  if (QT_QTDBUS_FOUND AND NOT WIN32)
+-     set(DIRS ${DIRS} searchclient)
+-  endif (QT_QTDBUS_FOUND AND NOT WIN32)
+-  # make sure we build the daemon on all architectures - not as long as sys/socket.h is used
+-  if(NOT WIN32)
+-    set(DIRS ${DIRS} daemon)
+-  endif(NOT WIN32)
+-  message(STATUS "Index libraries were found. strigidaemon will be built.")
+-else (CLucene_FOUND OR HyperEstraier_FOUND OR SQLite_FOUND)
+-  message("** No index libraries were found. strigidaemon will not be built.")
++if(NOT WIN32)
++  set(DIRS ${DIRS} htmlgui)
++endif(NOT WIN32)
++# searchclient needs htmlgui which is not compilable on win32
++if (QT_QTDBUS_FOUND AND NOT WIN32)
++  set(DIRS ${DIRS} searchclient)
++endif (QT_QTDBUS_FOUND AND NOT WIN32)
++# make sure we build the daemon on all architectures - not as long as sys/socket.h is used
++if(NOT WIN32)
++  set(DIRS ${DIRS} daemon)
++endif(NOT WIN32)
++
++if (NOT CLucene_FOUND)
++  message("** No CLucene libraries were found, so Strigi cannot use indexes.")
+   message("** It is recommended to install CLucene >= 0.9.16.")
+   message("** You will still be able to use deepfind, deepgrep and xmlindexer.")
+-endif (CLucene_FOUND OR HyperEstraier_FOUND OR SQLite_FOUND)
++endif (NOT CLucene_FOUND)
+ 
+ if (QT4_FOUND)
+   set(DIRS ${DIRS} archiveengine qclient)
+--- a/src/combinedindexer/CMakeLists.txt
++++ b/src/combinedindexer/CMakeLists.txt
+@@ -4,29 +4,7 @@
+ 	${strigi_BINARY_DIR}/src/streams
+ 	${strigi_SOURCE_DIR}/src/streams/strigi)
+ 
+-if (CLucene_FOUND)
+-    add_definitions(-DHAVE_CLUCENE)
+-    set(combinedindex_LIBS ${combinedindex_LIBS} cluceneindex)
+-    include_directories( ../luceneindexer )
+-endif (CLucene_FOUND)
+-
+-if (HyperEstraier_FOUND)
+-    add_definitions(-DHAVE_ESTRAIER)
+-    set(combinedindex_LIBS ${combinedindex_LIBS} estraierindex)
+-    include_directories( ../estraierindexer )
+-endif (HyperEstraier_FOUND)
+-
+-if (SQLite_FOUND)
+-    add_definitions(-DHAVE_SQLITE)
+-    set(combinedindex_LIBS ${combinedindex_LIBS} sqliteindex)
+-    include_directories( ../sqliteindexer )
+-endif (SQLite_FOUND)
+-
+ add_library(combinedindex combinedindexmanager.cpp)
+ 
+ target_link_libraries(combinedindex streamanalyzer grepindex
+     ${combinedindex_LIBS})
+-
+-#add_executable(combinedindexer combinedindexer.cpp)
+-#target_link_libraries(combinedindexer combinedindex filters)
+-
+--- a/src/combinedindexer/combinedindexmanager.cpp
++++ b/src/combinedindexer/combinedindexmanager.cpp
+@@ -21,6 +21,7 @@
+ #include <strigi/strigiconfig.h>
+ #include "variant.h"
+ 
++/*
+ #include "grepindexmanager.h"
+ #ifdef HAVE_CLUCENE
+ #include "cluceneindexmanager.h"
+@@ -34,20 +35,26 @@
+ #ifdef HAVE_SQLITE
+ #include "sqliteindexmanager.h"
+ #endif
++*/
+ 
+ #include "tssptr.h"
+ #include "query.h"
+ #include "indexeddocument.h"
+ #include "indexreader.h"
++#include "indexpluginloader.h"
+ #include <string>
+ #include <set>
+ #include <map>
+ using namespace std;
+ using namespace Strigi;
+ 
++/*
+ map<string, IndexManager*(*)(const char*)>
+ CombinedIndexManager::factories() {
+     map<string, IndexManager*(*)(const char*)> factories;
++    //IndexPluginLoader pluginloader;
++    //factories = pluginloader.factories();
++
+ #ifdef HAVE_ESTRAIER
+     factories["estraier"] = createEstraierIndexManager;
+ #endif
+@@ -74,7 +81,7 @@
+     }
+     return v;
+ }
+-
++*/
+ class CombinedIndexReader : public IndexReader {
+ private:
+     CombinedIndexManager* m;
+@@ -119,19 +126,21 @@
+ }
+ CombinedIndexManager::Private::~Private() {
+     if (writermanager) {
+-        delete writermanager;
++        IndexPluginLoader::deleteIndexManager(writermanager);
+     }
+ }
+ CombinedIndexManager::CombinedIndexManager(const string& type,
+         const string& indexdir) :p(new CombinedIndexManager::Private(this)) {
++    p->writermanager = IndexPluginLoader::createIndexManager(type.c_str(),
++        indexdir.c_str());
+     // determine the right index manager
+-    map<string, IndexManager*(*)(const char*)> l_factories = factories();
++/*    map<string, IndexManager*(*)(const char*)> l_factories = factories();
+     map<string, IndexManager*(*)(const char*)>::const_iterator f
+         = l_factories.find(type);
+     if (f == l_factories.end()) {
+         f = l_factories.begin();
+     }
+-    p->writermanager = f->second(indexdir.c_str());
++    p->writermanager = f->second(indexdir.c_str());*/
+ }
+ CombinedIndexManager::~CombinedIndexManager() {
+     delete p;
+@@ -148,14 +157,12 @@
+ CombinedIndexManager::addReadonlyIndex(const string& indexdir,
+         const string& type) {
+     removeReadonlyIndex(indexdir);
+-    // determine the right index manager
+-    map<string, IndexManager*(*)(const char*)> l_factories = factories();
+-    map<string, IndexManager*(*)(const char*)>::const_iterator f
+-        = l_factories.find(type);
+-    if (f == l_factories.end()) {
++
++    IndexManager* im = IndexPluginLoader::createIndexManager(type.c_str(),
++        indexdir.c_str());
++    if (im == 0) {
+         return;
+     }
+-    IndexManager* im = f->second(indexdir.c_str());
+     p->lock.lock();
+     p->readmanagers[indexdir] = im;
+     p->lock.unlock();
+--- a/src/combinedindexer/combinedindexmanager.h
++++ b/src/combinedindexer/combinedindexmanager.h
+@@ -40,10 +40,6 @@
+ 
+     void addReadonlyIndex(const std::string& indexdir, const std::string& type);
+     void removeReadonlyIndex(const std::string& indexdir);
+-
+-    static std::map<std::string, Strigi::IndexManager*(*)(const char*)>
+-        factories();
+-    static std::vector<std::string> backEnds();
+ };
+ 
+ #endif
+--- a/src/combinedindexer/tssptr.h
++++ b/src/combinedindexer/tssptr.h
+@@ -19,6 +19,7 @@
+  */
+ 
+ #include "strigi_thread.h"
++#include "indexpluginloader.h"
+ 
+ // thread safe smart pointer
+ template <class T>
+@@ -61,7 +62,7 @@
+             int c = --(p->count);
+             p->lock.unlock();
+             if (c == 0) {
+-                delete p->p;
++                Strigi::IndexPluginLoader::deleteIndexManager(p->p);
+                 delete p;
+             }
+             p = 0;
+--- a/src/daemon/daemon.cpp
++++ b/src/daemon/daemon.cpp
+@@ -21,6 +21,7 @@
+ #include "interface.h"
+ #include "daemonconfigurator.h"
+ #include "combinedindexmanager.h"
++#include "indexpluginloader.h"
+ 
+ #include "indexscheduler.h"
+ #include "analyzerconfiguration.h"
+@@ -151,7 +152,7 @@
+ }
+ void
+ printBackendList() {
+-    std::vector<std::string> backends = CombinedIndexManager::backEnds();
++    std::vector<std::string> backends = IndexPluginLoader::indexNames();
+     for ( unsigned int i = 0; i < backends.size(); ++i ) {
+         printf( "%s\n", backends[i].c_str() );
+     }
+@@ -194,7 +195,7 @@
+ }
+ void
+ ensureBackend( const std::string& backendName ) {
+-    std::vector<std::string> backends = CombinedIndexManager::backEnds();
++    std::vector<std::string> backends = IndexPluginLoader::indexNames();
+     if ( std::find( backends.begin(), backends.end(), backendName ) == backends.end() ) {
+         fprintf( stderr, "Unknown backend type: %s\n", backendName.c_str() );
+         exit( 2 );
+--- a/src/daemon/eventlistener/inotifylistener.cpp
++++ b/src/daemon/eventlistener/inotifylistener.cpp
+@@ -39,6 +39,38 @@
+ using namespace std;
+ using namespace Strigi;
+ 
++namespace {
++    /*!
++    * @param path string containing path to check
++    * Appends the terminating char to path.
++    * Under Windows that char is '\', '/' under *nix
++    */
++    string fixPath (string path)
++    {
++        if ( path.c_str() == NULL || path.length() == 0 )
++            return "";
++
++        string temp(path);
++
++    #ifdef HAVE_WINDOWS_H
++        size_t l= temp.length();
++        char* t = (char*)temp.c_str();
++        for (size_t i=0;i<l;i++){
++            if ( t[i] == '\\' )
++                t[i] = '/';
++        }
++        temp[0] = tolower(temp.at(0));
++    #endif
++
++        char separator = '/';
++
++        if (temp[temp.length() - 1 ] != separator)
++            temp += separator;
++
++        return temp;
++    }
++}
++
+ class MatchString {
+     string m_fixed_val;
+ 
+@@ -345,59 +377,38 @@
+     m_toWatch.clear();
+     m_toIndex.clear();
+     
+-    Strigi::FileLister lister (m_pindexerconfiguration);
+-    
+     for (set<string>::iterator iter = m_newDirs.begin();
+          iter != m_newDirs.end(); iter++)
+     {
+-        string filename;
+-        time_t mTime;
+-        
+-        lister.startListing( *iter);
+-        
+-        while (lister.nextFile( filename, mTime) != -1)
+-            m_toIndex.insert (make_pair (filename, mTime));
+-
+-        //TODO: look for a better solution
+-        set<string> temp = lister.getListedDirs();
+-        for (set<string>::iterator it = temp.begin(); it != temp.end(); it++)
+-            m_toWatch.insert(*it);
+-    }
+-    
+-    map <string, time_t> indexedFiles = m_pManager->indexReader()->files(0);
+-    map<string,time_t>::iterator mi = indexedFiles.begin();
+-
+-    while (mi != indexedFiles.end()) {
+-        map<string,time_t>::iterator it = m_toIndex.find(mi->first);
+-
+-        if (it == m_toIndex.end()) {
+-            // file has been deleted since last run
+-            m_events.push_back (new Event (Event::DELETED, mi->first));
++        DirLister lister(m_pindexerconfiguration);
++        string path;
++        vector<pair<string, struct stat> > dirs;
++
++        lister.startListing (*iter);
++        int ret = lister.nextDir(path, dirs);
++
++        while (ret != -1) {
++            for (vector<pair<string, struct stat> >::iterator iter = dirs.begin();
++                 iter != dirs.end(); iter++)
++            {
++                struct stat stats = iter->second;
+ 
+-            // no more useful, speedup into dirsRemoved
+-            map<string,time_t>::iterator itrm = mi;
+-            mi++;
+-            indexedFiles.erase(itrm);
+-        }
+-        else if (mi->second < it->second) {
+-            // file has been updated since last run
+-            m_events.push_back (new Event (Event::UPDATED, mi->first));
+-            m_toIndex.erase (it);
+-            mi++;
+-        }
+-        else {
+-            // file has NOT been changed since last run,
+-            // we keep our indexed information
+-            m_toIndex.erase (it);
+-            mi++;
++                if (S_ISDIR(stats.st_mode)) {
++                    //dir
++                    m_toWatch.insert (iter->first);
++                }
++                else if (S_ISREG(stats.st_mode)) {
++                    //file
++                    m_events.push_back (new Event (Event::CREATED, iter->first));
++                }
++            }
++            ret = lister.nextDir(path, dirs);
+         }
+     }
+ 
+-    // now m_toIndex contains only files created since the last run
+-    for (mi = m_toIndex.begin(); mi != m_toIndex.end(); mi++)
+-        m_events.push_back (new Event (Event::CREATED, mi->first));
+-
+     m_nomoreIndexedDirs.clear();
++    set<string> alreadyWatched;
++    
+     for (map<int, string>::iterator it = watchedDirs.begin();
+          it != watchedDirs.end(); it++)
+     {
+@@ -405,7 +416,68 @@
+         if (match == m_toWatch.end()) // dir is no longer watched
+             m_nomoreIndexedDirs.insert(it->second);
+         else // dir is already watched
+-            m_toWatch.erase (match);
++            alreadyWatched.insert (*match);
++    }
++
++    // look for updated dirs
++    m_toIndex.clear();
++    for (set<string>::iterator iter = alreadyWatched.begin();
++         iter != alreadyWatched.end(); iter++)
++    {
++        // retrieve files contained into the already watched dirs
++
++        Strigi::DirLister lister (m_pindexerconfiguration);
++
++        lister.startListing (*iter);
++
++        string path;
++        vector<pair<string, struct stat> > dirs;
++        int ret = lister.nextDir(path, dirs);
++
++        while (ret != -1) {
++            cout << "path = " << path << endl;
++
++            for (vector<pair<string, struct stat> >::iterator iter = dirs.begin();
++                 iter != dirs.end(); iter++)
++            {
++                struct stat stats = iter->second;
++                if (S_ISREG(stats.st_mode))
++                    m_toIndex.insert (make_pair (iter->first, stats.st_mtime));
++            }
++            ret = lister.nextDir(path, dirs);
++        }
++
++        map <string, time_t> indexedFiles;
++        m_pManager->indexReader()->getChildren (*iter, indexedFiles);
++        for (map<string, time_t>::iterator iter = m_toIndex.begin();
++             iter != m_toIndex.end(); iter++)
++        {
++            map<string, time_t>::iterator match;
++            match = indexedFiles.find(iter->first);
++            if (match == indexedFiles.end()) {
++                // new file created
++                m_events.push_back (new Event (Event::CREATED, iter->first));
++            }
++            else if (match->second < iter->second) {
++                // file has been updated
++                m_events.push_back (new Event (Event::UPDATED, iter->first));
++            }
++        }
++        m_toIndex.clear();
++    }
++
++    // remove no more indexed items
++    for (set<string>::iterator iter = m_nomoreIndexedDirs.begin();
++         iter != m_nomoreIndexedDirs.end(); iter++)
++    {
++        map <string, time_t> indexedFiles;
++        m_pManager->indexReader()->getChildren (*iter, indexedFiles);
++
++        for (map<string,time_t>::iterator mi = indexedFiles.begin();
++             mi != indexedFiles.end(); mi++)
++        {
++            m_events.push_back (new Event (Event::DELETED, mi->first));
++        }
+     }
+     
+     if (testInterrupt()) {
+@@ -738,25 +810,35 @@
+                     // a new directory has been created or an already watched
+                     // directory has been moved into a watched place
+                     
+-                    m_toIndex.clear();
+                     m_toWatch.clear();
+ 
+-                    FileLister lister(m_pindexerconfiguration);
+-                    
+-                    string filename;
+-                    time_t mTime;
+-                    while (lister.nextFile( filename, mTime) != -1)
+-                        m_toIndex.insert (make_pair (filename, mTime));
+-
+-                    m_toWatch = lister.getListedDirs();
+-
+-                    for (map<string,time_t>::iterator i = m_toIndex.begin();
+-                         i != m_toIndex.end(); i++)
+-                    {
+-                        Event* event = new Event (Event::CREATED, i->first);
+-                        events.push_back (event);
++                    DirLister lister(m_pindexerconfiguration);
++                    string path;
++                    vector<pair<string, struct stat> > dirs;
++
++                    lister.startListing (file);
++                    int ret = lister.nextDir(path, dirs);
++
++                    while (ret != -1) {
++                        for (vector<pair<string, struct stat> >::iterator iter = dirs.begin();
++                             iter != dirs.end(); iter++)
++                        {
++                            struct stat stats = iter->second;
++                            
++                            if (S_ISDIR(stats.st_mode)) {
++                                //dir
++                                m_toWatch.insert (iter->first);
++                            }
++                            else if (S_ISREG(stats.st_mode)) {
++                                //file
++                                Event* event = new Event (Event::CREATED,
++                                                          iter->first);
++                                events.push_back (event);
++                            }
++                        }
++                        ret = lister.nextDir(path, dirs);
+                     }
+-
++                    
+                     // add new watches
+                     addWatches (m_toWatch);
+ 
+@@ -1066,8 +1148,9 @@
+     // we've to de-index all files contained into the deleted/moved directory
+     if (m_pManager)
+     {
+-        // all indexed files
+-        map<string, time_t> indexedFiles = m_pManager->indexReader()->files(0);
++        // all indexed files contained into dir
++        map<string, time_t> indexedFiles;
++        m_pManager->indexReader()->getChildren(dir, indexedFiles);
+ 
+         // remove all entries that were contained into the removed dir
+         for (map<string, time_t>::iterator it = indexedFiles.begin();
+@@ -1076,12 +1159,8 @@
+             if (enableInterrupt && testInterrupt())
+                 break;
+             
+-            string::size_type pos = (it->first).find (dir);
+-            if (pos == 0)
+-            {
+-                Event* event = new Event (Event::DELETED, it->first);
+-                newEvents.push_back (event);
+-            }
++            Event* event = new Event (Event::DELETED, it->first);
++            newEvents.push_back (event);
+         }
+     }
+     else
+--- a/src/daemon/eventlistener/pollinglistener.cpp
++++ b/src/daemon/eventlistener/pollinglistener.cpp
+@@ -38,6 +38,38 @@
+ using namespace std;
+ using namespace Strigi;
+ 
++namespace {
++    /*!
++    * @param path string containing path to check
++    * Appends the terminating char to path.
++    * Under Windows that char is '\', '/' under *nix
++    */
++    string fixPath (string path)
++    {
++        if ( path.c_str() == NULL || path.length() == 0 )
++            return "";
++
++        string temp(path);
++
++    #ifdef HAVE_WINDOWS_H
++        size_t l= temp.length();
++        char* t = (char*)temp.c_str();
++        for (size_t i=0;i<l;i++){
++            if ( t[i] == '\\' )
++                t[i] = '/';
++        }
++        temp[0] = tolower(temp.at(0));
++    #endif
++
++        char separator = '/';
++
++        if (temp[temp.length() - 1 ] != separator)
++            temp += separator;
++
++        return temp;
++    }
++}
++
+ PollingListener::PollingListener() :EventListener("PollingListener") {
+     setState(Idling);
+     STRIGI_MUTEX_INIT(&m_mutex);
+@@ -123,35 +155,7 @@
+ 
+     STRIGI_MUTEX_UNLOCK (&m_mutex);
+ }
+-/*!
+-* @param path string containing path to check
+-* Appends the terminating char to path.
+-* Under Windows that char is '\', '/' under *nix
+-*/
+-string fixPath (string path)
+-{
+-    if ( path.c_str() == NULL || path.length() == 0 )
+-        return "";
+-
+-    string temp(path);
+-
+-#ifdef HAVE_WINDOWS_H
+-    size_t l= temp.length();
+-    char* t = (char*)temp.c_str();
+-    for (size_t i=0;i<l;i++){
+-        if ( t[i] == '\\' )
+-            t[i] = '/';
+-    }
+-    temp[0] = tolower(temp.at(0));
+-#endif
+-
+-    char separator = '/';
+ 
+-    if (temp[temp.length() - 1 ] != separator)
+-        temp += separator;
+-
+-    return temp;
+-}
+ void
+ PollingListener::addWatches(const set<string>& watches, bool enableInterrupt) {
+     for (set<string>::iterator iter = watches.begin();
+--- a/src/daemon/interface.cpp
++++ b/src/daemon/interface.cpp
+@@ -18,9 +18,10 @@
+  * Boston, MA 02110-1301, USA.
+  */
+ #include "interface.h"
+-#include "indexreader.h"
+ #include "combinedindexmanager.h"
++#include "indexreader.h"
+ #include "indexwriter.h"
++#include "indexpluginloader.h"
+ #include "indexscheduler.h"
+ #include "eventlistener.h"
+ #include "streamanalyzer.h"
+@@ -69,7 +70,7 @@
+ }
+ vector<string>
+ Interface::getBackEnds() {
+-    return manager.backEnds();
++    return IndexPluginLoader::indexNames();
+ }
+ map<string, string>
+ Interface::getStatus() {
+--- a/src/estraierindexer/CMakeLists.txt
++++ b/src/estraierindexer/CMakeLists.txt
+@@ -3,15 +3,26 @@
+ include_directories( ../streamanalyzer ../streams ${EST_INCLUDE_DIR}
+ 	${strigi_BINARY_DIR}/src/streams
+ 	${strigi_SOURCE_DIR}/src/streams/strigi)
++link_directories(${EST_LIBDIR})
++set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EST_CFLAGS}")
+ 
+-add_library(estraierindex
++if(WIN32)
++  # this is needed to have mingw, cygwin and msvc libs installed in one directory
++  if(MSVC)
++    set(prefix msvc_strigiindex_)
++  elseif(CYGWIN)
++    set(prefix cyg_strigiindex_)
++  elseif(MINGW)
++    set(prefix mingw_strigiindex_)
++  endif(MSVC)
++else(WIN32)
++  set(prefix strigiindex_)
++endif(WIN32)
++add_library(estraier MODULE
+ 	estraierindexmanager.cpp
+         estraierindexreader.cpp
+ 	estraierindexwriter.cpp
+ )
+-
+-target_link_libraries(estraierindex streamanalyzer ${EST_LIBS})
+-
+-add_executable(estraierindexer estraierindexer.cpp)
+-target_link_libraries(estraierindexer estraierindex)
+-
++set_target_properties(estraier PROPERTIES PREFIX ${prefix})
++target_link_libraries(estraier ${EST_LIBS})
++install(TARGETS estraier LIBRARY DESTINATION ${LIB_DESTINATION}/strigi)
+--- a/src/estraierindexer/estraierindexmanager.cpp
++++ b/src/estraierindexer/estraierindexmanager.cpp
+@@ -22,20 +22,21 @@
+ #include "estraierindexreader.h"
+ #include "estraierindexwriter.h"
+ #include "strigi_thread.h"
++#include "indexplugin.h"
++#include <iostream>
+ #include <assert.h>
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <unistd.h>
++#include <errno.h>
+ #include "stgdirent.h" //our dirent compatibility header... uses native if available
+ using namespace std;
+ using namespace Strigi;
+ 
+-pthread_mutex_t EstraierIndexManager::lock = PTHREAD_MUTEX_INITIALIZER;
++/* define and export the index factory */
++REGISTER_STRIGI_INDEXMANAGER(EstraierIndexManager)
+ 
+-Strigi::IndexManager*
+-createEstraierIndexManager(const char* path) {
+-    return new EstraierIndexManager(path);
+-}
++pthread_mutex_t EstraierIndexManager::lock = PTHREAD_MUTEX_INITIALIZER;
+ 
+ EstraierIndexManager::EstraierIndexManager(const char* dbd)
+         : dblock(lock), dbdir(dbd) {
+--- a/src/estraierindexer/estraierindexmanager.h
++++ b/src/estraierindexer/estraierindexmanager.h
+@@ -56,7 +56,4 @@
+     void deleteIndex();
+ };
+ 
+-Strigi::IndexManager*
+-createEstraierIndexManager(const char* path);
+-
+ #endif
+--- a/src/estraierindexer/estraierindexreader.cpp
++++ b/src/estraierindexer/estraierindexreader.cpp
+@@ -37,7 +37,7 @@
+     // build the phrase string
+ 
+     // write the part of the query that matches the document context
+-    string inphrase, exphrase;
++/*    string inphrase, exphrase;
+     set<string> terms;
+     const map<string, set<string> >& includes = query.includes();
+     map<string, set<string> >::const_iterator i = includes.find("");
+@@ -60,9 +60,9 @@
+             phrase += " ANDNOT ";
+         }
+         phrase += *j;
+-    }
++    } */
+     ESTCOND* cond = est_cond_new();
+-    printf("%s", phrase.c_str());
++/*    printf("%s", phrase.c_str());
+     if (phrase.length() > 0) {
+         est_cond_set_phrase(cond, phrase.c_str());
+     }
+@@ -93,7 +93,7 @@
+             est_cond_add_attr(cond, att.c_str());
+         }
+     }
+-    printf("\n");
++    printf("\n");*/ 
+ 
+     return cond;
+ }
+@@ -136,7 +136,7 @@
+     return n;
+ }
+ vector<IndexedDocument>
+-EstraierIndexReader::query(const Query& query) {
++EstraierIndexReader::query(const Query& query, int off, int max) {
+     ESTCOND* cond = createCondition(query);
+     est_cond_set_max(cond, 10);
+     int n;
+@@ -182,9 +182,17 @@
+     free(ids);
+     return results;
+ }
+-map<string, time_t>
+-EstraierIndexReader::files(char depth) {
+-    map<string, time_t> files;
++void
++EstraierIndexReader::getHits(const Strigi::Query& query,
++        const std::vector<std::string>& fields,
++        const std::vector<Strigi::Variant::Type>& types,
++        std::vector<std::vector<Strigi::Variant> >& result,
++        int off, int max) {
++}
++void
++EstraierIndexReader::getChildren(const std::string& parent,
++            std::map<std::string, time_t>& children) {
++/*    map<string, time_t> files;
+     ESTCOND* cond = est_cond_new();
+     string q = "depth NUMEQ 0";
+     est_cond_add_attr(cond, q.c_str());
+@@ -208,7 +216,7 @@
+     // clean up
+     est_cond_delete(cond);
+     free(ids);
+-    return files;
++    return files;*/
+ }
+ int32_t
+ EstraierIndexReader::countDocuments() {
+@@ -231,16 +239,10 @@
+     manager->deref();
+     return count;
+ }
+-int64_t
+-EstraierIndexReader::documentId(const string& uri) {
+-    ESTDB* db = manager->ref();
+-    int64_t id = est_db_uri_to_id(db, uri.c_str());
+-    manager->deref();
+-    return id;
+-}
+ time_t
+-EstraierIndexReader::mTime(int64_t docid) {
++EstraierIndexReader::mTime(const std::string& uri) {
+     ESTDB* db = manager->ref();
++    int64_t docid = est_db_uri_to_id(db, uri.c_str());
+     time_t mtime = -1;
+     char *cstr = est_db_get_doc_attr(db, docid, "@mdate");
+     if (cstr) {
+@@ -248,12 +250,7 @@
+         free(cstr);
+     }
+     manager->deref();
+-    return mtime;
+-
+-}
+-time_t
+-EstraierIndexReader::mTime(const std::string& uri) {
+-    return mTime(documentId(uri));
++    return docid;
+ }
+ vector<string>
+ EstraierIndexReader::fieldNames() {
+@@ -264,3 +261,14 @@
+             const string& labeltype) {
+     return vector<pair<string,uint32_t> >();
+ }
++int32_t
++EstraierIndexReader::countKeywords(const std::string& keywordprefix,
++        const std::vector<std::string>& fieldnames) {
++    return -1;
++}
++vector<string>
++EstraierIndexReader::keywords(const std::string& keywordmatch,
++        const std::vector<std::string>& fieldnames,
++        uint32_t max, uint32_t offset) {
++    return vector<string>();
++}
+--- a/src/estraierindexer/estraierindexreader.h
++++ b/src/estraierindexer/estraierindexreader.h
+@@ -36,14 +36,14 @@
+     static ESTCOND* createCondition(const Strigi::Query&);
+     static const char* mapId(const std::string& id);
+ public:
++    std::vector<Strigi::IndexedDocument> query(const Strigi::Query&,
++        int off, int max);
++    void getHits(const Strigi::Query& query,
++        const std::vector<std::string>& fields,
++        const std::vector<Strigi::Variant::Type>& types,
++        std::vector<std::vector<Strigi::Variant> >& result,
++        int off, int max);
+     int32_t countHits(const Strigi::Query&);
+-    std::vector<Strigi::IndexedDocument> query(const Strigi::Query&);
+-    std::map<std::string, time_t> files(char depth);
+-    int countDocuments();
+-    int32_t countWords();
+-    int64_t indexSize();
+-    int64_t documentId(const std::string& uri);
+-    time_t mTime(int64_t docid);
+     time_t mTime(const std::string& uri);
+     std::vector<std::string> fieldNames();
+     std::vector<std::pair<std::string,uint32_t> > histogram(
+@@ -54,6 +54,11 @@
+     std::vector<std::string> keywords(const std::string& keywordmatch,
+         const std::vector<std::string>& fieldnames,
+         uint32_t max, uint32_t offset);
++    void getChildren(const std::string& parent,
++            std::map<std::string, time_t>& children);
++    int countDocuments();
++    int32_t countWords();
++    int64_t indexSize();
+ };
+ 
+ #endif
+--- a/src/estraierindexer/estraierindexwriter.cpp
++++ b/src/estraierindexer/estraierindexwriter.cpp
+@@ -49,16 +49,16 @@
+ EstraierIndexWriter::addValue(const AnalysisResult* idx,
+         const RegisteredField* field, const string& value) {
+     ESTDOC* doc = static_cast<ESTDOC*>(idx->writerData());
+-    if (field->getKey() == "size") {
++    if (field->key() == "size") {
+         est_doc_add_attr(doc, "@size", value.c_str());
+-    } else if (field->getKey() == "title") {
++    } else if (field->key() == "title") {
+         est_doc_add_attr(doc, "@title", value.c_str());
+     } else {
+-        est_doc_add_attr(doc, field->getKey().c_str(), value.c_str());
++        est_doc_add_attr(doc, field->key().c_str(), value.c_str());
+     }
+ }
+ void
+-EstraierIndexWriter::startAnalysis(AnalysisResult* idx) {
++EstraierIndexWriter::startAnalysis(const AnalysisResult* idx) {
+     // allocate a new estraier document
+     ESTDOC* doc = est_doc_new();
+     idx->setWriterData(doc);
+--- a/src/estraierindexer/estraierindexwriter.h
++++ b/src/estraierindexer/estraierindexwriter.h
+@@ -31,7 +31,7 @@
+     const std::string indexpath;
+ 
+ protected:
+-    void startAnalysis(Strigi::AnalysisResult*);
++    void startAnalysis(const Strigi::AnalysisResult*);
+     void addValue(const Strigi::AnalysisResult*, const Strigi::RegisteredField* field,
+         const std::string& value);
+     void addValue(const Strigi::AnalysisResult*, const Strigi::RegisteredField* field,
+--- a/src/estraierindexer/tests/CMakeLists.txt
++++ b/src/estraierindexer/tests/CMakeLists.txt
+@@ -1,9 +1,10 @@
+ include_directories(.. ../../indexertests)
++link_directories(${EST_LIBDIR})
+ 
+ CREATE_TEST_SOURCELIST(Tests testrunner.cpp EstraierTest.cpp)
+ 
+ ADD_EXECUTABLE(testrunner ${Tests} )
+-target_link_libraries(testrunner streams estraierindex indexertests)
++target_link_libraries(testrunner streams indexertests)
+ 
+ SET (TestsToRun ${Tests})
+ REMOVE (TestsToRun testrunner.cpp)
+--- a/src/estraierindexer/tests/EstraierTest.cpp
++++ b/src/estraierindexer/tests/EstraierTest.cpp
+@@ -1,5 +1,6 @@
+ #include <strigi/strigiconfig.h>
+-#include "estraierindexmanager.h"
++#include "indexpluginloader.h"
++#include "indexmanager.h"
+ #include "indexmanagertests.h"
+ #include "indexwritertests.h"
+ #include "indexreadertests.h"
+@@ -15,7 +16,8 @@
+ 
+     // initialize a directory for writing and an indexmanager
+     mkdir(path, S_IRUSR|S_IWUSR|S_IXUSR);
+-    EstraierIndexManager* manager = new EstraierIndexManager(path);
++    Strigi::IndexManager *manager
++            = Strigi::IndexPluginLoader::createIndexManager("estraier", path);
+ 
+     Strigi::AnalyzerConfiguration ic;
+     IndexManagerTests tests(manager, ic);
+--- a/src/htmlgui/strigihtmlgui.cpp
++++ b/src/htmlgui/strigihtmlgui.cpp
+@@ -27,6 +27,7 @@
+ #include <dirent.h>
+ #include <sstream>
+ #include <fstream>
++#include <iostream>
+ #include <sys/stat.h>
+ #include <stdlib.h>
+ #include <string.h>
+@@ -56,7 +57,9 @@
+ }
+ void
+ StrigiHtmlGui::printHtmlHeader(ostream& out) {
+-    out << "<?xml version='1.0' encoding='utf-8'?>\n"
++    // FIXME: extra spaces added at the beginning as a wordaround because
++    // KIO discards several first chars for unknown reason
++    out << "                           <?xml version='1.0' encoding='utf-8'?>\n"
+         "<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' "
+         "'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>\n"
+         "<html xmlns='http://www.w3.org/1999/xhtml'>"
+@@ -190,12 +193,15 @@
+     if (i != params.end()) {
+         max = atoi(i->second.c_str());
+     }
+-    if (max == 0) max = 10;
++    if (max <= 0 || max > 1000) max = 10;
+     int off = 0;
+     i = params.find("o");
+     if (i != params.end()) {
+         off = atoi(i->second.c_str());
+     }
++    if (off < 0) {
++        off = 0;
++    }
+     string selectedtab;
+     i = params.find("t");
+     if (i != params.end()) {
+@@ -215,20 +221,23 @@
+         bool doother = true;
+         tabs = readTabQueries();
+         if (tabs.size() == 0) {
+-            tabs["Images"] = "content.mime_type:image*";
+-            tabs["Mail"] = "content.mime_type:message/*";
+-            tabs["Web"] = "content.mime_type:text/html";
+-            tabs["Text"] = "content.mime_type:text/*";
++            tabs["Images"] = "mimeType:image*";
++            tabs["Mail"] = "mimeType:message/*";
++            tabs["Web"] = "mimeType:text/html";
++            tabs["Text"] = "mimeType:text/*";
+         }
+         map<string, string>::const_iterator j;
+         string otherq = query;
+         for (j = tabs.begin(); j != tabs.end(); ++j) {
+-            string q = query+' '+j->second;
++            string q = query;
++            if (q != j->second) {
++                q += ' ' + j->second;
++            }
+             int c = p->strigi.countHits(q);
+             if (c > 0) {
+                 hitcounts[j->first] = c;
+                 doother &= c < count;
+-        otherq += " -" + j->second;
++                otherq += " -" + j->second;
+                 if (j->first == selectedtab || activetab.size() == 0) {
+                     activetab = j->first;
+                     activequery = q;
+@@ -424,9 +433,9 @@
+         icon = "<div class='iconbox'><img class='icon' src='"+icon;
+         icon += "'/></div>\n";
+     }
+-    t = doc.properties.find("audio.title");
++    t = doc.properties.find("title");
+     if (t == doc.properties.end()) {
+-        t = doc.properties.find("email.subject");
++        t = doc.properties.find("subject");
+     }
+     size_t l = doc.uri.rfind('/');
+     if (t != doc.properties.end()) {
+--- a/src/luceneindexer/cluceneindexmanager.cpp
++++ b/src/luceneindexer/cluceneindexmanager.cpp
+@@ -27,12 +27,17 @@
+ #include <CLucene.h>
+ #include "cluceneindexwriter.h"
+ #include "cluceneindexreader.h"
++#include "indexplugin.h"
+ #include <iostream>
+ #include <sys/types.h>
+ #include <time.h>
+ #include "timeofday.h"
+ #include "stgdirent.h" //our dirent compatibility header... uses native if available
+ 
++
++/* define and export the index factory */
++REGISTER_STRIGI_INDEXMANAGER(CLuceneIndexManager)
++
+ using namespace lucene::index;
+ using lucene::analysis::standard::StandardAnalyzer;
+ using lucene::store::FSDirectory;
+@@ -51,6 +56,11 @@
+     indexwriter = 0;
+     writer = new CLuceneIndexWriter(this);
+     analyzer = new StandardAnalyzer();
++    if (path == ":memory:") {
++        ramdirectory = new lucene::store::RAMDirectory();
++    } else {
++        ramdirectory = 0;
++    }
+     mtime = 0;
+ 
+     //remove any old segments lying around from crashes, etc
+@@ -67,6 +77,7 @@
+         r->second = 0;
+     }
+     closeWriter();
++    delete ramdirectory;
+     delete analyzer;
+     if (--numberOfManagers == 0) {
+ // temporarily commented out because of problem with clucene
+@@ -116,16 +127,22 @@
+ void
+ CLuceneIndexManager::openWriter(bool truncate) {
+     try {
+-        if (!truncate && IndexReader::indexExists(dbdir.c_str())) {
++        if (ramdirectory) {
++            indexwriter = new IndexWriter(ramdirectory, analyzer, true);
++        } else if (!truncate && IndexReader::indexExists(dbdir.c_str())) {
+             if (IndexReader::isLocked(dbdir.c_str())) {
+                 IndexReader::unlock(dbdir.c_str());
+             }
+             indexwriter = new IndexWriter(dbdir.c_str(), analyzer, false);
+         } else {
+-            indexwriter = new IndexWriter(dbdir.c_str(), analyzer, true, true);
++            indexwriter = new IndexWriter(dbdir.c_str(), analyzer, true);
+         }
+     } catch (CLuceneError& err) {
+-        printf("could not create writer: %s\n", err.what());
++        fprintf(stderr, "could not create writer: %s\n", err.what());
++        indexwriter = 0;
++    } catch (...) {
++        fprintf(stderr, "Unknown exception was thrown.");
++        indexwriter = 0;
+     }
+ }
+ void
+@@ -201,3 +218,4 @@
+     mtime = t.tv_sec;
+     lock.unlock();
+ }
++
+--- a/src/luceneindexer/cluceneindexmanager.h
++++ b/src/luceneindexer/cluceneindexmanager.h
+@@ -22,7 +22,6 @@
+ 
+ #include <strigi/strigiconfig.h>
+ #include "indexmanager.h"
+-//#include "querybitset.h"
+ #include <strigi_thread.h>
+ #include <string>
+ #include <map>
+@@ -38,6 +37,9 @@
+         class IndexWriter;
+         class IndexReader;
+     }
++    namespace store {
++        class RAMDirectory;
++    }
+ }
+ 
+ class CLuceneIndexReader;
+@@ -50,13 +52,14 @@
+     std::map<STRIGI_THREAD_TYPE, CLuceneIndexReader*> readers;
+     CLuceneIndexWriter* writer;
+     lucene::index::IndexWriter* indexwriter;
+-    //Strigi::QueryBitsetCache bitsets;
+     lucene::analysis::Analyzer* analyzer;
+     time_t mtime;
+     static int numberOfManagers;
+ 
+     void openWriter(bool truncate=false);
+ public:
++    lucene::store::RAMDirectory* ramdirectory;
++
+     explicit CLuceneIndexManager(const std::string& path);
+     ~CLuceneIndexManager();
+ 
+@@ -65,7 +68,6 @@
+     Strigi::IndexReader* indexReader();
+     Strigi::IndexWriter* indexWriter();
+     CLuceneIndexReader* luceneReader();
+-//    Strigi::QueryBitsetCache* bitSets();
+     int32_t docCount();
+     int64_t indexSize();
+     void deleteIndex();
+@@ -74,7 +76,4 @@
+     void setIndexMTime();
+ };
+ 
+-CLUCENEINDEXER_EXPORT Strigi::IndexManager*
+-createCLuceneIndexManager(const char* path);
+-
+ #endif
+--- a/src/luceneindexer/cluceneindexreader.cpp
++++ b/src/luceneindexer/cluceneindexreader.cpp
+@@ -137,7 +137,11 @@
+     doccount = -1;
+     wordcount = -1;
+     try {
+-        reader = lucene::index::IndexReader::open(dbdir.c_str());
++        if (manager->ramdirectory) {
++            reader = lucene::index::IndexReader::open(manager->ramdirectory);
++        } else {
++            reader = lucene::index::IndexReader::open(dbdir.c_str());
++        }
+         //fprintf(stderr,
+         //"reader at %s: %i\n", dbdir.c_str(), reader->numDocs());
+     } catch (CLuceneError& err) {
+@@ -585,14 +589,14 @@
+     vector<int32_t>::const_iterator i;
+     struct tm t;
+     for (i = v.begin(); i < v.end(); ++i) {
+-         time_t ti = *i;
++        time_t ti = *i;
+ #ifdef _WIN32
+         t = *localtime( &ti );   // is thread-safe on win32
+ #else
+-         localtime_r(&ti, &t);
++        localtime_r(&ti, &t);
+ #endif
+-         int32_t c = 10000*t.tm_year + 100*t.tm_mon + t.tm_mday;
+-         m[c]++;
++        int32_t c = 10000*t.tm_year + 100*t.tm_mon + t.tm_mday;
++        m[c]++;
+     }
+     vector<pair<string,uint32_t> > h;
+     h.reserve(m.size());
+--- a/src/luceneindexer/cluceneindexwriter.cpp
++++ b/src/luceneindexer/cluceneindexwriter.cpp
+@@ -240,8 +240,11 @@
+             if (t && _tcsncmp(t, prefixText, prefixLen) == 0) {
+                 try {
+                     reader->deleteDocument(i);
++                } catch (CLuceneError& err) {
++                    cerr << "Could not delete document '" << entry
++                        << "' from the index: " << err.what() << endl;
+                 } catch (...) {
+-                    fprintf(stderr, "could not delete document");
++                    cerr << "This should not happen." << endl;
+                 }
+             }
+             _CLDELETE(d);
+--- a/src/luceneindexer/CMakeLists.txt
++++ b/src/luceneindexer/CMakeLists.txt
+@@ -19,42 +19,44 @@
+     ADD_DEFINITIONS(-DUNICODE)
+ ENDIF(WIN32)
+ 
+-# CLucene requires exception support and has no support for visibility=hidden
+-# so we must use the default (i.e. public) value for -fvisibility
++# CLucene requires exception support
+ IF(NOT WIN32)
+     IF (CMAKE_COMPILER_IS_GNUCXX)
+         set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions")
+     ENDIF(CMAKE_COMPILER_IS_GNUCXX)
+ ENDIF(NOT WIN32)
+-IF(__STRIGI_HAVE_GCC_VISIBILITY)
+-    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=default")
+-ENDIF(__STRIGI_HAVE_GCC_VISIBILITY)
++# In the past, we though we needed to use -fvisibility=default for compiling
++# this library. This appears not to be the case anymore.
++#IF(__STRIGI_HAVE_GCC_VISIBILITY)
++#    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=default")
++#ENDIF(__STRIGI_HAVE_GCC_VISIBILITY)
+ 
+ set(cluceneindex_SRCS
+-#        PrefixFilter.cpp
+-        cluceneindexmanager.cpp
+-        cluceneindexreader.cpp
+-        cluceneindexwriter.cpp
+-        jsgzipcompressstream.cpp
+-	tcharutils.cpp
++    cluceneindexmanager.cpp
++    cluceneindexreader.cpp
++    cluceneindexwriter.cpp
++    jsgzipcompressstream.cpp
++    tcharutils.cpp
+ )
+ 
+-add_library(cluceneindex SHARED ${cluceneindex_SRCS})
+-
+-set_target_properties(cluceneindex
+-    PROPERTIES VERSION ${STRIGI_VERSION}
+-    SOVERSION ${STRIGI_VERSION_MAJOR}
+-    DEFINE_SYMBOL MAKE_CLUCENEINDEXER_LIB
+-)
+-
+-target_link_libraries(cluceneindex streamanalyzer ${CLUCENE_LIBRARY})
++if(WIN32)
++  # this is needed to have mingw, cygwin and msvc libs installed in one directory
++  if(MSVC)
++    set(prefix msvc_strigiindex_)
++  elseif(CYGWIN)
++    set(prefix cyg_strigiindex_)
++  elseif(MINGW)
++    set(prefix mingw_strigiindex_)
++  endif(MSVC)
++else(WIN32)
++  set(prefix strigiindex_)
++endif(WIN32)
++add_library(clucene MODULE ${cluceneindex_SRCS})
++set_target_properties(clucene PROPERTIES PREFIX ${prefix})
++target_link_libraries(clucene ${CLUCENE_LIBRARY})
++install(TARGETS clucene LIBRARY DESTINATION ${LIB_DESTINATION}/strigi)
+ 
+ add_executable(luceneindexer luceneindexer.cpp)
+-target_link_libraries(luceneindexer cluceneindex)
++target_link_libraries(luceneindexer streamanalyzer)
+ 
+ install(TARGETS luceneindexer RUNTIME DESTINATION bin)
+-install(TARGETS cluceneindex
+-	LIBRARY DESTINATION ${LIB_DESTINATION}
+-	RUNTIME DESTINATION bin
+-	ARCHIVE DESTINATION  ${LIB_DESTINATION}
+-)
+--- a/src/luceneindexer/indexdump/CMakeLists.txt
++++ b/src/luceneindexer/indexdump/CMakeLists.txt
+@@ -1,4 +1,4 @@
+ include_directories(${CLUCENE_LIBRARY_DIR} ${CLUCENE_INCLUDE_DIR}
+ 	${ICONV_INCLUDE_DIR} ..)
+-add_executable(indexdump indexdump.cpp)
+-target_link_libraries(indexdump ${CLUCENE_LIBRARY} cluceneindex)
++add_executable(indexdump indexdump.cpp ../tcharutils.cpp)
++target_link_libraries(indexdump streamanalyzer ${CLUCENE_LIBRARY})
+--- a/src/luceneindexer/luceneindexer.cpp
++++ b/src/luceneindexer/luceneindexer.cpp
+@@ -18,9 +18,8 @@
+  * Boston, MA 02110-1301, USA.
+  */
+ #include <strigi/strigiconfig.h>
+-#include <CLucene.h>
+ #include "diranalyzer.h"
+-#include "cluceneindexmanager.h"
++#include "indexpluginloader.h"
+ #include "analyzerconfiguration.h"
+ #include <iostream>
+ #include <sys/types.h>
+@@ -65,10 +64,13 @@
+     Strigi::AnalyzerConfiguration ic;
+     ic.setFilters(filters);
+     try {
+-        Strigi::IndexManager *manager = createCLuceneIndexManager(argv[1]);
+-        Strigi::DirAnalyzer analyzer(*manager, ic);
+-        analyzer.analyzeDir(argv[2]);
+-        delete manager;
++        Strigi::IndexManager *manager
++            = Strigi::IndexPluginLoader::createIndexManager("clucene", argv[1]);
++        if (manager) {
++            Strigi::DirAnalyzer analyzer(*manager, ic);
++            analyzer.analyzeDir(argv[2]);
++            Strigi::IndexPluginLoader::deleteIndexManager(manager);
++        }
+     } catch (...) {
+         cerr << "error while creating index" << endl;
+     }
+--- a/src/luceneindexer/tcharutils.h
++++ b/src/luceneindexer/tcharutils.h
+@@ -25,9 +25,9 @@
+ #include <string>
+ #include <strigi/strigiconfig.h>
+ 
+-std::string CLUCENEINDEXER_EXPORT wchartoutf8(const wchar_t*);
+-std::wstring CLUCENEINDEXER_EXPORT utf8toucs2(const char*);
+-std::string CLUCENEINDEXER_EXPORT wchartoutf8(const std::wstring&);
+-std::wstring CLUCENEINDEXER_EXPORT utf8toucs2(const std::string&);
++std::string wchartoutf8(const wchar_t*);
++std::wstring utf8toucs2(const char*);
++std::string wchartoutf8(const std::wstring&);
++std::wstring utf8toucs2(const std::string&);
+ 
+ #endif
+--- a/src/luceneindexer/tests/CLuceneTest.cpp
++++ b/src/luceneindexer/tests/CLuceneTest.cpp
+@@ -1,5 +1,6 @@
+ #include <strigi/strigiconfig.h>
+-#include "cluceneindexmanager.h"
++#include "indexpluginloader.h"
++#include "indexmanager.h"
+ #include "indexmanagertests.h"
+ #include "indexwritertests.h"
+ #include "indexreadertests.h"
+@@ -23,7 +24,12 @@
+ #else
+     mkdir(path, S_IRUSR|S_IWUSR|S_IXUSR);
+ #endif
+-    Strigi::IndexManager* manager = createCLuceneIndexManager(path);
++    Strigi::IndexManager* manager
++        = Strigi::IndexPluginLoader::createIndexManager("clucene", path);
++    if (manager == 0) {
++        founderrors++;
++        return founderrors;
++    }
+ 
+     Strigi::AnalyzerConfiguration ic;
+     IndexManagerTests tests(manager, ic);
+@@ -39,7 +45,7 @@
+     rtests.testAll();
+ 
+     // close and clean up the manager
+-    delete manager;
++    Strigi::IndexPluginLoader::deleteIndexManager(manager);
+ 
+     // clean up data
+     std::string cmd = "rm -r ";
+--- a/src/luceneindexer/tests/CMakeLists.txt
++++ b/src/luceneindexer/tests/CMakeLists.txt
+@@ -3,7 +3,7 @@
+ CREATE_TEST_SOURCELIST(Tests testrunner.cpp CLuceneTest.cpp)
+ 
+ ADD_EXECUTABLE(testrunner-lucene ${Tests} )
+-target_link_libraries(testrunner-lucene streams cluceneindex indexertests)
++target_link_libraries(testrunner-lucene streamanalyzer indexertests)
+ 
+ SET (TestsToRun ${Tests})
+ REMOVE (TestsToRun testrunner.cpp)
+--- a/src/sqliteindexer/CMakeLists.txt
++++ b/src/sqliteindexer/CMakeLists.txt
+@@ -4,14 +4,23 @@
+ 	${SQLITE_LIBRARY_DIR} ${SQLITE_INCLUDE_DIR}
+ 	${strigi_BINARY_DIR}/src/streams)
+ 
+-add_library(sqliteindex
++if(WIN32)
++  # this is needed to have mingw, cygwin and msvc libs installed in one directory
++  if(MSVC)
++    set(prefix msvc_strigiindex_)
++  elseif(CYGWIN)
++    set(prefix cyg_strigiindex_)
++  elseif(MINGW)
++    set(prefix mingw_strigiindex_)
++  endif(MSVC)
++else(WIN32)
++  set(prefix strigiindex_)
++endif(WIN32)
++add_library(sqlite MODULE
+ 	sqliteindexmanager.cpp
+         sqliteindexreader.cpp
+ 	sqliteindexwriter.cpp
+ )
+-
+-target_link_libraries(sqliteindex streamanalyzer ${SQLITE_LIBRARIES})
+-
+-add_executable(sqliteindexer sqliteindexer.cpp)
+-target_link_libraries(sqliteindexer sqliteindex sqlite3)
+-
++set_target_properties(sqlite PROPERTIES PREFIX ${prefix})
++target_link_libraries(sqlite ${SQLITE_LIBRARIES})
++install(TARGETS sqlite LIBRARY DESTINATION ${LIB_DESTINATION}/strigi)
+--- a/src/sqliteindexer/sqliteindexmanager.cpp
++++ b/src/sqliteindexer/sqliteindexmanager.cpp
+@@ -21,15 +21,15 @@
+ #include "sqliteindexreader.h"
+ #include "sqliteindexwriter.h"
+ #include "strigi_thread.h"
++#include "indexplugin.h"
++#include <iostream>
+ using namespace std;
+ using namespace Strigi;
+ 
+-pthread_mutex_t SqliteIndexManager::lock = PTHREAD_MUTEX_INITIALIZER;
++/* define and export the index factory */
++REGISTER_STRIGI_INDEXMANAGER(SqliteIndexManager)
+ 
+-Strigi::IndexManager*
+-createSqliteIndexManager(const char* path) {
+-    return new SqliteIndexManager(path);
+-}
++pthread_mutex_t SqliteIndexManager::lock = PTHREAD_MUTEX_INITIALIZER;
+ 
+ SqliteIndexManager::SqliteIndexManager(const char* dbfile) {
+     dblock = lock;
+@@ -51,6 +51,7 @@
+ }
+ sqlite3*
+ SqliteIndexManager::opendb(const char* path) {
++    // check if the database already exists
+     sqlite3* db;
+     int r = sqlite3_open(path, &db);
+     // any value other than SQLITE_OK is an error
+@@ -85,9 +86,8 @@
+ ;
+     r = sqlite3_exec(db, sql, 0, 0, 0);
+     if (r != SQLITE_OK) {
+-        fprintf(stderr, "could not create table %i %s\n", r,
+-            sqlite3_errmsg(db));
+-        exit(1);
++        //fprintf(stderr, "could not create table %i %s.\n", r,
++        //    sqlite3_errmsg(db));
+     }
+ 
+     // create temporary tables
+--- a/src/sqliteindexer/sqliteindexmanager.h
++++ b/src/sqliteindexer/sqliteindexmanager.h
+@@ -54,7 +54,5 @@
+     static std::string escapeSqlValue(const std::string& value);
+     static sqlite3* opendb(const char*);
+ };
+-Strigi::IndexManager*
+-createSqliteIndexManager(const char* path);
+ 
+ #endif
+--- a/src/sqliteindexer/sqliteindexreader.cpp
++++ b/src/sqliteindexer/sqliteindexreader.cpp
+@@ -20,6 +20,7 @@
+ #include "sqliteindexreader.h"
+ #include "sqliteindexmanager.h"
+ #include <set>
++#include <iostream>
+ #include <sstream>
+ using namespace std;
+ using namespace Strigi;
+@@ -61,7 +62,7 @@
+         q << "f"<<a<<".count*1.0/w"<<a<<".count";
+     }
+     if (n > 0) {
+-    q <<") p ";
++        q <<") p ";
+     }
+     q <<" from ";
+     for (int i=0; i<n; ++i) {
+@@ -93,16 +94,55 @@
+ 
+     return q.str();
+ }
++string
++createQuery(const Query& query, int off, int max) {
++    // TODO: makeing a query with wildcards slows things down, so we must
++    // think about reordering them
++    // although we'll never be able to manage queries like 'a% b% c%'
++    ostringstream q;
++    q << "select path from ";
++    //
++    for (int i=0; i<n; ++i) {
++        q << "words w" << i << ",";
++    }
++    for (int i=0; i<n; ++i) {
++        q << "filewords f" << i << ",";
++    }
++    q <<"files where ";
++    for (int i=0; i<n; ++i) {
++        q << "w" << i << ".word like ? and w" << i << ".wordid = f" << i
++            << ".wordid and ";
++    }
++    for (int i=1; i<n; ++i) {
++        q << "f0.fileid = f" << i << ".fileid and ";
++    }
++    if (n > 0) {
++        q <<"f0.fileid = files.fileid ";
++    }
++    if (filterpath) {
++        if (n > 0) q <<"and ";
++        q <<"files.path like ? ";
++    }
++    if (n > 0) q <<"group by fa.fileid order by p ";
++    q << "limit " << max << " offset " << off;
++
++    return q.str();
++}
+ int
+ SqliteIndexReader::countHits(const Strigi::Query& q) {
+     // very inefficient: needs refactoring
+     vector<IndexedDocument> r = query(q, 0, 1000000);
+     return r.size();
+ }
++string
++createQuery(const Query& query) {
++    return "select path from files;";
++}
+ vector<IndexedDocument>
+ SqliteIndexReader::query(const Strigi::Query& query, int off, int max) {
+-    string q;
+-    // replace * by %
++    string sql(createQuery(query, off, max));
++    vector<IndexedDocument> results;
++/*    // replace * by %
+     size_t p = q.find('*');
+     while (p != string::npos) {
+         q.replace(p, 1, "%");
+@@ -116,7 +156,6 @@
+     }
+     // split up in terms
+     set<string> terms = split(q);
+-    vector<IndexedDocument> results;
+     if (terms.size() == 0) return results;
+     string pathfilter;
+     set<string>::iterator i = terms.begin();
+@@ -132,17 +171,17 @@
+     if (terms.size() == 0 && pathfilter.length() == 0) return results;
+ 
+     string sql = createQuery(terms.size(), pathfilter.length() > 0);
+-
++*/
+     sqlite3* db = manager->ref();
+     sqlite3_stmt* stmt;
+     int r = sqlite3_prepare(db, sql.c_str(), -1, &stmt, 0);
+     if (r != SQLITE_OK) {
+-        printf("could not prepare query '%s': %s\n", sql.c_str(),
++        fprintf(stderr, "could not prepare query '%s': %s\n", sql.c_str(),
+             sqlite3_errmsg(db));
+         manager->deref();
+         return results;
+     }
+-    int j = 1;
++/*    int j = 1;
+     for (i=terms.begin(); i!=terms.end(); ++i) {
+         sqlite3_bind_text(stmt, j++, i->c_str(), i->length(),
+             SQLITE_STATIC);
+@@ -150,7 +189,7 @@
+     if (pathfilter.length() > 0) {
+         sqlite3_bind_text(stmt, j, pathfilter.c_str(), pathfilter.length(),
+             SQLITE_STATIC);
+-    }
++    }*/
+     r = sqlite3_step(stmt);
+     while (r == SQLITE_ROW) {
+         IndexedDocument doc;
+@@ -245,3 +284,10 @@
+     vector<string> k;
+     return k;
+ }
++void
++SqliteIndexReader::getHits(const Strigi::Query& query,
++        const std::vector<std::string>& fields,
++        const std::vector<Strigi::Variant::Type>& types,
++        std::vector<std::vector<Strigi::Variant> >& result,
++        int off, int max) {
++}
+--- a/src/sqliteindexer/sqliteindexreader.h
++++ b/src/sqliteindexer/sqliteindexreader.h
+@@ -48,6 +48,11 @@
+     std::vector<std::string> keywords(const std::string& keywordmatch,
+         const std::vector<std::string>& fieldnames,
+         uint32_t max, uint32_t offset);
++    void getHits(const Strigi::Query& query,
++        const std::vector<std::string>& fields,
++        const std::vector<Strigi::Variant::Type>& types,
++        std::vector<std::vector<Strigi::Variant> >& result,
++        int off, int max);
+ };
+ 
+ #endif
+--- a/src/sqliteindexer/sqliteindexwriter.cpp
++++ b/src/sqliteindexer/sqliteindexwriter.cpp
+@@ -183,6 +183,7 @@
+         = content.find(wdata->id);
+ 
+     if (m == content.end()) {
++        delete wdata;
+         return;
+     }
+ 
+@@ -199,6 +200,7 @@
+             sqlite3_errmsg(db));
+         content.erase(m->first);
+         manager->deref();
++        delete wdata;
+         return;
+     }
+     map<string, int>::const_iterator i = m->second.begin();
+@@ -209,7 +211,7 @@
+             SQLITE_STATIC);
+         sqlite3_bind_int(stmt, 3, i->second);
+         r = sqlite3_step(stmt);
+-        if (r != 21) { // what is 21?
++        if (r != SQLITE_DONE) { // what is 21?
+             fprintf(stderr, "could not write content into database: %i %s\n", r,
+                 sqlite3_errmsg(db));
+         }
+--- a/src/sqliteindexer/tests/CMakeLists.txt
++++ b/src/sqliteindexer/tests/CMakeLists.txt
+@@ -3,7 +3,7 @@
+ CREATE_TEST_SOURCELIST(Tests testrunner.cpp SqliteTest.cpp simpletest.cpp)
+ 
+ ADD_EXECUTABLE(sqlitetest ${Tests} )
+-target_link_libraries(sqlitetest streams sqliteindex indexertests)
++target_link_libraries(sqlitetest streams indexertests)
+ 
+ SET (TestsToRun ${Tests})
+ REMOVE (TestsToRun testrunner.cpp)
+--- a/src/sqliteindexer/tests/simpletest.cpp
++++ b/src/sqliteindexer/tests/simpletest.cpp
+@@ -1,5 +1,6 @@
+ #include <strigi/strigiconfig.h>
+-#include "sqliteindexmanager.h"
++#include "indexpluginloader.h"
++#include "indexmanager.h"
+ #include "indexwriter.h"
+ #include "indexreader.h"
+ #include "analyzerconfiguration.h"
+@@ -38,13 +39,14 @@
+     mkdir(path, S_IRUSR|S_IWUSR|S_IXUSR);
+     string p(path);
+     p += "/test.db";
+-    IndexManager* manager = createSqliteIndexManager(p.c_str());
++    Strigi::IndexManager* manager
++        = Strigi::IndexPluginLoader::createIndexManager("sqlite", p.c_str());
+     IndexWriter* writer = manager->indexWriter();
+     IndexReader* reader = manager->indexReader();
+     addAndCount(writer, reader, 1);
+ 
+     // close and clean up the manager
+-    delete manager;
++    Strigi::IndexPluginLoader::deleteIndexManager(manager);
+ 
+     // clean up data
+ /*    std::string cmd = "rm -r ";
+--- a/src/sqliteindexer/tests/SqliteTest.cpp
++++ b/src/sqliteindexer/tests/SqliteTest.cpp
+@@ -1,5 +1,5 @@
+ #include <strigi/strigiconfig.h>
+-#include "sqliteindexmanager.h"
++#include "indexpluginloader.h"
+ #include "indexmanagertests.h"
+ #include "indexwritertests.h"
+ #include "indexreadertests.h"
+@@ -18,7 +18,8 @@
+     mkdir(path, S_IRUSR|S_IWUSR|S_IXUSR);
+     string p(path);
+     p += "/test.db";
+-    Strigi::IndexManager* manager = createSqliteIndexManager(p.c_str());
++    Strigi::IndexManager* manager
++        = Strigi::IndexPluginLoader::createIndexManager("sqlite", p.c_str());
+ 
+     Strigi::AnalyzerConfiguration ic;
+     IndexManagerTests tests(manager, ic);
+@@ -34,7 +35,7 @@
+     rtests.testAll();
+ */
+     // close and clean up the manager
+-    delete manager;
++    Strigi::IndexPluginLoader::deleteIndexManager(manager);
+ 
+     // clean up data
+     std::string cmd = "rm -r ";
+--- a/src/streamanalyzer/classproperties.cpp
++++ b/src/streamanalyzer/classproperties.cpp
+@@ -25,7 +25,6 @@
+ using namespace Strigi;
+ using namespace std;
+ 
+-const string ClassProperties::Private::empty;
+ ClassProperties::ClassProperties() :p(new Private()) {
+ }
+ ClassProperties::ClassProperties(const Private& pr) :p(new Private(pr)) {}
+@@ -70,12 +69,12 @@
+ const string&
+ ClassProperties::localizedName(const string& locale) const {
+     map<string,Localized>::iterator i = p->localized.find(locale);
+-    return (i == p->localized.end()) ?Private::empty :i->second.name;
++    return (i == p->localized.end()) ?empty() :i->second.name;
+ }
+ const string&
+ ClassProperties::localizedDescription(const string& locale) const {
+     map<string,Localized>::iterator i = p->localized.find(locale);
+-    return (i == p->localized.end()) ?Private::empty :i->second.description;
++    return (i == p->localized.end()) ?empty() :i->second.description;
+ }
+ const vector<string>&
+ ClassProperties::parentUris() const {
+--- a/src/streamanalyzer/CMakeLists.txt
++++ b/src/streamanalyzer/CMakeLists.txt
+@@ -26,6 +26,7 @@
+ 	htmlsaxanalyzer.cpp
+ 	id3v2throughanalyzer.cpp
+         indexreader.cpp
++	indexpluginloader.cpp
+ 	lineeventanalyzer.cpp
+ 	m3ustreamanalyzer.cpp
+ 	mimeeventanalyzer.cpp
+@@ -97,6 +98,9 @@
+ 	fieldproperties.h
+ 	fieldtypes.h
+ 	indexeddocument.h
++	indexreader.h
++	indexmanager.h
++	indexplugin.h
+ 	indexwriter.h
+ 	streamanalyzer.h
+ 	streamanalyzerfactory.h
+--- a/src/streamanalyzer/fieldproperties.cpp
++++ b/src/streamanalyzer/fieldproperties.cpp
+@@ -25,7 +25,6 @@
+ using namespace Strigi;
+ using namespace std;
+ 
+-const string FieldProperties::Private::empty;
+ FieldProperties::FieldProperties() :p(new Private()) {
+ }
+ FieldProperties::FieldProperties(const Private& pr) :p(new Private(pr)) {}
+@@ -102,12 +101,12 @@
+ const string&
+ FieldProperties::localizedName(const string& locale) const {
+     map<string,Localized>::iterator i = p->localized.find(locale);
+-    return (i == p->localized.end()) ?Private::empty :i->second.name;
++    return (i == p->localized.end()) ?empty() :i->second.name;
+ }
+ const string&
+ FieldProperties::localizedDescription(const string& locale) const {
+     map<string,Localized>::iterator i = p->localized.find(locale);
+-    return (i == p->localized.end()) ?Private::empty :i->second.description;
++    return (i == p->localized.end()) ?empty() :i->second.description;
+ }
+ const vector<string>&
+ FieldProperties::parentUris() const {
+--- a/src/streamanalyzer/fieldpropertiesdb.cpp
++++ b/src/streamanalyzer/fieldpropertiesdb.cpp
+@@ -39,7 +39,8 @@
+ #include <map>
+ #include <iostream>
+ #include <list>
+-#include <string>
++#include <set>
++
+ using namespace Strigi;
+ using namespace std;
+ 
+@@ -47,8 +48,8 @@
+ public:
+     map<string, FieldProperties> properties;
+     map<string, ClassProperties> classes;
+-    static FieldProperties emptyField;
+-    static ClassProperties emptyClass;
++    static const FieldProperties& emptyField();
++    static const ClassProperties& emptyClass();
+ 
+     Private();
+     static vector<string> getdirs(const string&);
+@@ -94,8 +95,16 @@
+ 
+ };
+ 
+-FieldProperties FieldPropertiesDb::Private::emptyField;
+-ClassProperties FieldPropertiesDb::Private::emptyClass;
++const FieldProperties&
++FieldPropertiesDb::Private::emptyField() {
++    static const FieldProperties e;
++    return e;
++}
++const ClassProperties&
++FieldPropertiesDb::Private::emptyClass() {
++    static const ClassProperties f;
++    return f;
++}
+ 
+ FieldPropertiesDb&
+ FieldPropertiesDb::db() {
+@@ -112,7 +121,7 @@
+     map<std::string, FieldProperties>::const_iterator j
+         = p->properties.find(uri);
+     if (j == p->properties.end()) {
+-        return FieldPropertiesDb::Private::emptyField;
++        return FieldPropertiesDb::Private::emptyField();
+     } else {
+         return j->second;
+     }
+@@ -126,7 +135,7 @@
+ FieldPropertiesDb::classes(const std::string& uri) const {
+     map<std::string, ClassProperties>::const_iterator j = p->classes.find(uri);
+     if (j == p->classes.end()) {
+-        return FieldPropertiesDb::Private::emptyClass;
++        return FieldPropertiesDb::Private::emptyClass();
+     } else {
+         return j->second;
+     }
+@@ -178,8 +187,12 @@
+ 
+     vector<string> dirs = getXdgDirs();
+     vector<string>::const_iterator i;
++    set<string> done;
+     for (i=dirs.begin(); i!=dirs.end(); i++) {
+-        loadProperties(*i);
++        if (done.find(*i) == done.end()) {
++            done.insert(*i);
++            loadProperties(*i);
++        }
+     }
+ 
+     // Generate childUris, applicable* and locales values.
+@@ -255,6 +268,9 @@
+     props.uri = FieldRegister::filenameFieldName;
+     properties[FieldRegister::filenameFieldName] = props;
+ 
++    props.uri = FieldRegister::mimetypeFieldName;
++    properties[FieldRegister::mimetypeFieldName] = props;
++
+     props.uri = FieldRegister::parentLocationFieldName;
+     props.tokenized = false;
+     properties[FieldRegister::parentLocationFieldName] = props;
+@@ -263,13 +279,23 @@
+ FieldPropertiesDb::Private::loadProperties(const string& dir) {
+     string pdir = dir + "/strigi/fieldproperties/";
+     DIR* d = opendir(pdir.c_str());
+-    if (!d) return;
++    if (!d) {
++        pdir = dir;
++        d = opendir(pdir.c_str());
++    }
++    if (!d) {
++        return;
++    }
++    if (pdir[pdir.length()-1] != '/') {
++        pdir.append("/");
++    }
+     struct dirent* de = readdir(d);
+     struct stat s;
+     char* data = 0;
+     while (de) {
+         string path(pdir+de->d_name);
+-        if (!stat(path.c_str(), &s) && S_ISREG(s.st_mode)) {
++        if (path.length() >= 5 && path.substr(path.length()-5) == ".rdfs" &&
++                !stat(path.c_str(), &s) && S_ISREG(s.st_mode)) {
+             FILE* f = fopen(path.c_str(), "r");
+             if (f) {
+                 // read the entire file at once
+--- a/src/streamanalyzer/fieldproperties_private.h
++++ b/src/streamanalyzer/fieldproperties_private.h
+@@ -24,12 +24,18 @@
+ #include "fieldproperties.h"
+ #include "fieldtypes.h"
+ 
++namespace {
++    const std::string& empty() {
++        static std::string e;
++        return e;
++    }
++}
++
+ namespace Strigi {
+ 
+ class FieldProperties::Private {
+ friend class FieldPropertiesDb;
+ public:
+-    static const std::string empty;
+     std::string uri;
+     std::string name;
+     std::string typeuri;
+@@ -69,7 +75,6 @@
+ class ClassProperties::Private {
+ friend class FieldPropertiesDb;
+ public:
+-    static const std::string empty;
+     std::string uri;
+     std::string name;
+     std::string description;
+--- a/src/streamanalyzer/fieldtypes.cpp
++++ b/src/streamanalyzer/fieldtypes.cpp
+@@ -103,7 +103,7 @@
+             = FieldPropertiesDb::db().properties(fieldname);
+         if (!props.valid()) {
+             cerr << "WARNING: field '" << fieldname << "' is not defined in "
+-                ".fieldproperties ontology database." << endl;
++                "any rdfs ontology database." << endl;
+ 	    // creates a field with defaults (stringType and no parents)
+             FieldPropertiesDb::db().addField(fieldname);
+         }
+--- a/src/streamanalyzer/filelister.cpp
++++ b/src/streamanalyzer/filelister.cpp
+@@ -47,34 +47,37 @@
+ using namespace std;
+ using namespace Strigi;
+ 
+-/*!
+-* @param path string containing path to check
+-* Appends the terminating char to path.
+-* Under Windows that char is '\', '/' under *nix
+-*/
+-string fixPath (string path)
++namespace
+ {
+-    if ( path.c_str() == NULL || path.length() == 0 )
+-        return "";
+-
+-    string temp(path);
+-
+-#ifdef HAVE_WINDOWS_H
+-    size_t l= temp.length();
+-    char* t = (char*)temp.c_str();
+-    for (size_t i=0;i<l;i++){
+-        if ( t[i] == '\\' )
+-            t[i] = '/';
+-    }
+-    temp[0] = tolower(temp.at(0));
+-#endif
++    /*!
++    * @param path string containing path to check
++    * Appends the terminating char to path.
++    * Under Windows that char is '\', '/' under *nix
++    */
++    string fixPath (string path)
++    {
++        if ( path.c_str() == NULL || path.length() == 0 )
++            return "";
++
++        string temp(path);
++
++    #ifdef HAVE_WINDOWS_H
++        size_t l= temp.length();
++        char* t = (char*)temp.c_str();
++        for (size_t i=0;i<l;i++){
++            if ( t[i] == '\\' )
++                t[i] = '/';
++        }
++        temp[0] = tolower(temp.at(0));
++    #endif
+ 
+-    char separator = '/';
++        char separator = '/';
+ 
+-    if (temp[temp.length() - 1 ] != separator)
+-        temp += separator;
++        if (temp[temp.length() - 1 ] != separator)
++            temp += separator;
+ 
+-    return temp;
++        return temp;
++    }
+ }
+ 
+ class FileLister::Private {
+--- a/src/streamanalyzer/filelister.h
++++ b/src/streamanalyzer/filelister.h
+@@ -45,7 +45,6 @@
+ 
+ namespace Strigi {
+ 
+-
+ class FileLister {
+ private:
+     class Private;
+@@ -72,7 +71,7 @@
+     void skipTillAfter(const std::string& lastToSkip);
+ };
+ 
+-class DirLister {
++class STRIGI_EXPORT DirLister {
+ private:
+     class Private;
+     Private* p;
+--- a/src/streamanalyzer/indexmanager.h
++++ b/src/streamanalyzer/indexmanager.h
+@@ -24,6 +24,9 @@
+ class IndexReader;
+ class IndexWriter;
+ 
++class IndexManager;
++void deleteIndexManager(Strigi::IndexManager* m);
++
+ /**
+  * Abstract interface that manages access to the IndexReader and IndexWriter
+  * instances provided by a particular index backend.
+@@ -38,6 +41,7 @@
+  * be used in the active thread.
+  **/
+ class IndexManager {
++friend void deleteIndexManager(Strigi::IndexManager* m);
+ public:
+     virtual ~IndexManager() {}
+     /**
+--- /dev/null
++++ b/src/streamanalyzer/indexplugin.h
+@@ -0,0 +1,40 @@
++/* This file is part of Strigi Desktop Search
++ *
++ * Copyright (C) 2007 Jos van den Oever <jos at vandenoever.info>
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public License
++ * along with this library; see the file COPYING.LIB.  If not, write to
++ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
++ * Boston, MA 02110-1301, USA.
++ */
++
++#ifndef STRIGI_INDEXPLUGIN_H
++#define STRIGI_INDEXPLUGIN_H
++#include <strigi/strigiconfig.h>
++
++/**
++ * @brief Macro to register functions for creating and deleting an indexmanager
++ *        in a plugin
++ *
++ * @param CLASS the name of the subclass of Strigi::IndexManager
++ */
++#define REGISTER_STRIGI_INDEXMANAGER(CLASS) extern "C" { \
++    STRIGI_EXPORT Strigi::IndexManager* createIndexManager(const char* dir) { \
++        return new CLASS(dir); \
++    } \
++    STRIGI_EXPORT void deleteIndexManager(Strigi::IndexManager* m) { \
++        delete m; \
++    } \
++}
++#endif
++
+--- /dev/null
++++ b/src/streamanalyzer/indexpluginloader.cpp
+@@ -0,0 +1,245 @@
++/* This file is part of Strigi Desktop Search
++ *
++ * Copyright (C) 2007 Jos van den Oever <jos at vandenoever.info>
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public License
++ * along with this library; see the file COPYING.LIB.  If not, write to
++ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
++ * Boston, MA 02110-1301, USA.
++ */
++#include "indexpluginloader.h"
++#include "indexmanager.h"
++#include <iostream>
++#include <stgdirent.h>
++#include <sys/stat.h>
++using namespace std;
++using namespace Strigi;
++
++#ifndef _WIN32
++#include <dlfcn.h>
++#define DLSYM dlsym
++#define DLCLOSE dlclose
++#else
++#define DLSYM GetProcAddress
++#define DLCLOSE FreeLibrary
++#endif
++
++#ifndef _WIN32
++typedef void* StgModuleType;
++#else
++#include <windows.h>
++typedef HMODULE StgModuleType;
++#endif
++
++// anonymous namespace for static variables
++namespace {
++    class Module {
++    private:
++        const StgModuleType mod;
++        Module(const Module&);
++        void operator=(const Module&);
++    public:
++        Strigi::IndexManager* (*create)(const char*);
++        void (*destroy)(Strigi::IndexManager*);
++        Module(StgModuleType m)
++            :mod(m) {}
++        ~Module() {
++// TODO: figure out why we get segfaults when cleaning up nicely
++            DLCLOSE(mod);
++        }
++    };
++    vector<string>
++    getdirs(const string& direnv) {
++        vector<string> dirs;
++        string::size_type lastp = 0;
++        string::size_type p = direnv.find(':');
++        while (p != string::npos) {
++            dirs.push_back(direnv.substr(lastp, p-lastp));
++            lastp = p+1;
++            p = direnv.find(':', lastp);
++        }
++        dirs.push_back(direnv.substr(lastp));
++        return dirs;
++    }
++    class ModuleList {
++    private:
++        map<std::string, Module*> modules;
++    public:
++        map<std::string, Module*>& mods() {
++            if (!initialized) initialize();
++            return modules;
++        };
++        map<void*, Module*> indexmanagers;
++        bool initialized;
++
++        ModuleList() {
++            initialized = false;
++        }
++        void initialize() {
++            initialized = true;
++            // load the plugins from the environment setting
++            string strigipluginpath;
++            if (getenv("STRIGI_PLUGIN_PATH")) {
++                strigipluginpath = getenv("STRIGI_PLUGIN_PATH");
++            }
++            vector<string> strigipluginpaths = getdirs(strigipluginpath);
++            if (strigipluginpath.size()) {
++                for (uint i=0; i<strigipluginpaths.size(); ++i) {
++                    IndexPluginLoader::loadPlugins(strigipluginpaths[i].c_str());
++                }
++            } else {
++                IndexPluginLoader::loadPlugins( LIBINSTALLDIR "/strigi");
++            }
++        }
++        ~ModuleList() {
++            // delete all leftover indexmanagers
++            // if code deletes the indexmanager on it's own, the error will
++            // appear here
++            map<void*, Module*>::iterator j;
++            for (j = indexmanagers.begin(); j != indexmanagers.end(); ++j) {
++                j->second->destroy(static_cast<IndexManager*>(j->first));
++            }
++            // unload all the modules
++            map<string, Module*>::iterator i;
++            for (i = modules.begin(); i != modules.end(); ++i) {
++                delete i->second;
++            }
++        }
++        void loadModule(const string& name, const string& dir);
++    };
++    void
++    ModuleList::loadModule(const string& name, const string& lib) {
++        // check if this module was already loaded
++        map<string, Module*>::iterator i = modules.find(name);
++        if (i != modules.end()) {
++            return;
++        }
++        StgModuleType handle;
++#ifdef HAVE_DLFCN_H
++        // do not use RTLD_GLOBAL here
++        // note: If neither RTLD_GLOBAL nor RTLD_LOCAL are specified,
++        // the default is RTLD_LOCAL.
++        handle = dlopen(lib.c_str(), RTLD_LAZY);
++#else
++        handle = LoadLibrary(lib.c_str());
++#endif
++        if (!handle) {
++#ifdef HAVE_DLFCN_H
++            cerr << "Could not load '" << lib << "':" << dlerror() << endl;
++#else
++            cerr << "Could not load '" << lib << "': GetLastError(): "
++                << GetLastError() << endl;
++#endif
++            return;
++        }
++        IndexManager*(*create)(const char*) = (IndexManager*(*)(const char*))
++            DLSYM(handle, "createIndexManager");
++        if (!create) {
++#ifndef WIN32
++            fprintf(stderr, "%s\n", dlerror());
++#else
++            fprintf(stderr, "GetLastError: %d\n", GetLastError());
++#endif
++            DLCLOSE(handle);
++            return;
++        }
++        void(*destroy)(IndexManager*) = (void(*)(IndexManager*))
++            DLSYM(handle, "deleteIndexManager");
++        if (!destroy) {
++#ifndef WIN32
++            fprintf(stderr, "%s\n", dlerror());
++#else
++            fprintf(stderr, "GetLastError: %d\n", GetLastError());
++#endif
++            DLCLOSE(handle);
++            return;
++        }
++        Module* module = new Module(handle);
++        module->create = create;
++        module->destroy = destroy;
++        modules[name] = module;
++    }
++    static ModuleList modules;
++}
++void
++IndexPluginLoader::loadPlugins(const char* d) {
++    DIR *dir = opendir(d);
++    if (dir == 0) {
++        return;
++    }
++    struct dirent* ent = readdir(dir);
++    string prefix("strigiindex_");
++#ifdef WIN32
++    string suffix(".dll");
++#else
++    string suffix(".so");
++#endif
++    while(ent) {
++        size_t len = strlen(ent->d_name);
++        const char* prepos = strstr(ent->d_name, prefix.c_str());
++        const char* sufpos = strstr(ent->d_name, suffix.c_str());
++        if (prepos && sufpos + suffix.length() == ent->d_name + len) {
++            len -= (prepos - ent->d_name) + prefix.length() + suffix.length();
++            string name(prepos + prefix.length(), len);
++            string pluginpath = d;
++            if (pluginpath[pluginpath.length()-1] != '/') {
++                pluginpath.append("/");
++            }
++            pluginpath.append(ent->d_name);
++            // check that the file is a regular file
++            struct stat s;
++            if (stat(pluginpath.c_str(), &s) == 0 && (S_IFREG & s.st_mode)) {
++                modules.loadModule(name, pluginpath);
++            }
++        }
++        ent = readdir(dir);
++    }
++    closedir(dir);
++}
++vector<string>
++IndexPluginLoader::indexNames() {
++    vector<string> names;
++    map<string, Module*>::const_iterator i = modules.mods().begin();
++    for (; i != modules.mods().end(); ++i) {
++        names.push_back(i->first);
++    }
++    return names;
++}
++IndexManager*
++IndexPluginLoader::createIndexManager(const char* name, const char* dir) {
++    // find the right plugin
++    map<string, Module*>::iterator i = modules.mods().find(name);
++    if (i == modules.mods().end()) {
++        return 0;
++    }
++    // create the indexmanager
++    IndexManager* im = i->second->create(dir);
++    if (im) {
++        // map the indexmanager to the module that created it, so we can delete
++        // it later
++        modules.indexmanagers[im] = i->second;
++    }
++    return im;
++}
++void
++IndexPluginLoader::deleteIndexManager(IndexManager* im) {
++    // find the right module
++    map<void*, Module*>::iterator i = modules.indexmanagers.find(im);
++    if (i == modules.indexmanagers.end()) {
++        return;
++    }
++    // let the module delete the indexmanager
++    i->second->destroy(im);
++    // remove the mapping from the map
++    modules.indexmanagers.erase(i);
++}
+--- /dev/null
++++ b/src/streamanalyzer/indexpluginloader.h
+@@ -0,0 +1,34 @@
++/* This file is part of Strigi Desktop Search
++ *
++ * Copyright (C) 2007 Jos van den Oever <jos at vandenoever.info>
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public License
++ * along with this library; see the file COPYING.LIB.  If not, write to
++ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
++ * Boston, MA 02110-1301, USA.
++ */
++#include <strigi/strigiconfig.h>
++#include <vector>
++#include <map>
++#include <string>
++
++namespace Strigi {
++  class IndexManager;
++  namespace IndexPluginLoader {
++    STRIGI_EXPORT void loadPlugins(const char* dir);
++    STRIGI_EXPORT std::vector<std::string> indexNames();
++    STRIGI_EXPORT Strigi::IndexManager* createIndexManager(const char* name,
++        const char* dir);
++    STRIGI_EXPORT void deleteIndexManager(Strigi::IndexManager* manager);
++  }
++}
+--- a/src/streamanalyzer/indexreader.h
++++ b/src/streamanalyzer/indexreader.h
+@@ -79,7 +79,7 @@
+      *                 @p parent will be placed.
+      **/
+     virtual void getChildren(const std::string& parent,
+-            std::map<std::string, time_t>& children) {}
++            std::map<std::string, time_t>& children) {};
+     /**
+      * Count the number of documents indexed in the index.
+      *
+--- a/src/streamanalyzer/queryparser.cpp
++++ b/src/streamanalyzer/queryparser.cpp
+@@ -120,7 +120,19 @@
+     }
+     return space+1;
+ }
+-
++void
++prependXesamNamespace(Query& query) {
++    // prepend the field names with the xesam namespace
++    // this will be elaborated once the xesam spec continues
++    vector<string>::iterator end(query.fields().end());
++    for (vector<string>::iterator i = query.fields().begin(); i != end; ++i) {
++        *i = "http://freedesktop.org/standards/xesam/1.0/core#" + *i;
++    }
++    std::vector<Query>::iterator qend(query.subQueries().end());
++    for (vector<Query>::iterator i = query.subQueries().begin(); i!=qend; ++i) {
++        prependXesamNamespace(*i);
++    }
++}
+ Query
+ QueryParser::buildQuery(const std::string& q) {
+     Query query;
+@@ -140,14 +152,7 @@
+         Query q = query.subQueries()[0];
+         query = q;
+     }
++    prependXesamNamespace(query);
+ 
+-    // prepend the field names with the xesam namespace
+-    // this will be elaborated once the xesam spec continues
+-    vector<string>::iterator end(query.fields().end());
+-    for (vector<string>::iterator i = query.fields().begin(); i != end; ++i) {
+-         *i = "http://freedesktop.org/standards/xesam/1.0/core#" + *i;
+-    }
+-    //cerr << "query: '" << q << "' : " << query.subQueries().size() << "'"
+-    //    << query.term().string() << "'" << endl;
+     return query;
+ }
+--- a/src/streams/base64inputstream.cpp
++++ b/src/streams/base64inputstream.cpp
+@@ -71,6 +71,7 @@
+ Base64InputStream::Base64InputStream(InputStream* i) :p(new Private(this, i)) {
+ }
+ Base64InputStream::~Base64InputStream() {
++    delete p;
+ }
+ Base64InputStream::Private::Private(Base64InputStream* bi, InputStream* i)
+         :p(bi), input(i) {
+--- a/src/streams/CMakeLists.txt
++++ b/src/streams/CMakeLists.txt
+@@ -73,7 +73,6 @@
+ 	stringterminatedsubstream.h
+ 	subinputstream.h
+         textutils.h
+-	strigi/jstreamsconfig.h
+ 	DESTINATION include/strigi
+ )
+ install(TARGETS streams
+--- a/src/streams/rpminputstream.cpp
++++ b/src/streams/rpminputstream.cpp
+@@ -141,15 +141,9 @@
+     m_status = cpio->status();
+ }
+ RpmInputStream::~RpmInputStream() {
+-    if (uncompressionStream) {
+-        delete uncompressionStream;
+-    }
+-    if (cpio) {
+-        delete cpio;
+-    }
+-    if (headerinfo) {
+-        delete headerinfo;
+-    }
++    delete uncompressionStream;
++    delete cpio;
++    delete headerinfo;
+ }
+ InputStream*
+ RpmInputStream::nextEntry() {
+--- a/src/streams/strigi/strigiconfig.h.cmake
++++ b/src/streams/strigi/strigiconfig.h.cmake
+@@ -47,7 +47,7 @@
+ // our needed types
+ #if !@HAVE_INT8_T@
+  #define HAVE_INT8_T 1
+- #if ${SIZEOF_CHAR}==1 //is char 1bit?
++ #if ${SIZEOF_CHAR}==1 //is char one byte?
+   typedef char int8_t;
+  #else
+   #error Could not determine type for int8_t!
+@@ -56,7 +56,7 @@
+ 
+ #if !@HAVE_UINT8_T@
+  #define HAVE_UINT8_T 1
+- #if ${SIZEOF_CHAR}==1 //is char 1bit?
++ #if ${SIZEOF_CHAR}==1 //is char one byte?
+   typedef unsigned char uint8_t;
+  #else
+   #error Could not determine type for uint8_t!
+@@ -65,7 +65,7 @@
+ 
+ #if !@HAVE_INT16_T@
+  #define HAVE_INT16_T 1
+- #if ${SIZEOF_SHORT}==2 //is short 2bits?
++ #if ${SIZEOF_SHORT}==2 //is short two bytes?
+   typedef short int16_t;
+  #else
+   #error Could not determine type for int16_t!
+@@ -74,7 +74,7 @@
+ 
+ #if !@HAVE_UINT16_T@
+  #define HAVE_UINT16_T 1
+- #if ${SIZEOF_SHORT}==2 //is short 2bits?
++ #if ${SIZEOF_SHORT}==2 //is short two bytes?
+   typedef unsigned short uint16_t;
+  #else
+   #error Could not determine type for uint16_t!
+@@ -83,9 +83,9 @@
+ 
+ #if !@HAVE_INT32_T@
+  #define HAVE_INT32_T 1
+- #if ${SIZEOF_INT}==4 //is int 4bits?
++ #if ${SIZEOF_INT}==4 //is int four bytes?
+   typedef int int32_t;
+- #elif ${SIZEOF_LONG}==4 //is long 4bits?
++ #elif ${SIZEOF_LONG}==4 //is long four bytes?
+   typedef long int32_t;
+  #else
+   #error Could not determine type for int32_t!
+@@ -94,9 +94,9 @@
+ 
+ #if !@HAVE_UINT32_T@
+  #define HAVE_UINT32_T 1
+- #if ${SIZEOF_INT}==4 //is int 4bits?
++ #if ${SIZEOF_INT}==4 //is int four bytes?
+   typedef unsigned int uint32_t;
+- #elif ${SIZEOF_LONG}==4 //is long 4bits?
++ #elif ${SIZEOF_LONG}==4 //is long four bytes?
+   typedef unsigned long uint32_t;
+  #else
+   #error Could not determine type for uint32_t!
+@@ -132,16 +132,6 @@
+  #define HAVE_UINT 1
+ #endif
+ 
+-#if !@HAVE_INTPTR_T@
+- typedef int intptr_t;
+- #define HAVE_INTPTR_T 1
+-#endif
+-
+-#if !@HAVE_SOCKLEN_T@
+- typedef int socklen_t;
+- #define HAVE_SOCKLEN_T 1
+-#endif
+-
+ #if !@HAVE_SIZE_T@
+  #ifndef _SIZE_T_DEFINED 
+   #ifndef HAVE_SIZE_T
+@@ -152,16 +142,6 @@
+  #endif
+ #endif
+ 
+-#if !@HAVE_SSIZE_T@
+- #ifndef _SSIZE_T_DEFINED 
+-  #ifndef HAVE_SSIZE_T
+-   typedef signed int ssize_t;
+-   #define HAVE_SSIZE_T 1
+-  #endif
+-  #define _SSIZE_T_DEFINED 1    // kdewin32 define
+- #endif
+-#endif
+-
+ #cmakedefine __STRIGI_HAVE_GCC_VISIBILITY
+ 
+ #cmakedefine ENABLE_NEWXESAM
+@@ -175,7 +155,7 @@
+  */
+ #ifdef __STRIGI_HAVE_GCC_VISIBILITY
+ #define STRIGI_EXPORT __attribute__ ((visibility("default")))
+-#define STRIGI_IMPORT STRIGI_EXPORT
++#define STRIGI_IMPORT
+ #elif defined(_WIN32) || defined(_WIN64)
+ #define STRIGI_EXPORT __declspec(dllexport)
+ #define STRIGI_IMPORT __declspec(dllimport)
+@@ -200,14 +180,6 @@
+ # endif
+ #endif
+ 
+-#ifndef CLUCENEINDEXER_EXPORT
+-# ifdef MAKE_CLUCENEINDEXER_LIB
+-#  define CLUCENEINDEXER_EXPORT STRIGI_EXPORT
+-# else
+-#  define CLUCENEINDEXER_EXPORT STRIGI_IMPORT
+-# endif
+-#endif
+-
+ #ifndef STRIGI_QTDBUSCLIENT_EXPORT
+ # ifdef MAKE_STRIGI_QTDBUSCLIENT_LIB
+ #  define STRIGI_QTDBUSCLIENT_EXPORT STRIGI_EXPORT
+--- a/src/strigicmd/strigicmd.cpp
++++ b/src/strigicmd/strigicmd.cpp
+@@ -18,7 +18,8 @@
+  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+  * Boston, MA 02110-1301, USA.
+  */
+-#include "combinedindexmanager.h"
++#include "indexpluginloader.h"
++#include "indexmanager.h"
+ #include "indexreader.h"
+ #include "indexwriter.h"
+ #include "indexeddocument.h"
+@@ -154,6 +155,10 @@
+ }
+ void
+ printBackends(const string& msg, const vector<string> backends) {
++    if (backends.size() == 0) {
++        pe(" No backends are available.\n");
++        return;
++    }
+     pe(msg.c_str());
+     pe(" Choose one from ");
+     for (uint j=0; j<backends.size()-1; ++j) {
+@@ -218,7 +223,7 @@
+ IndexManager*
+ getIndexManager(string& backend, const string& indexdir) {
+     // check arguments: backend
+-    const vector<string>& backends = CombinedIndexManager::backEnds();
++    const vector<string>& backends = IndexPluginLoader::indexNames();
+     // if there is only one backend, the backend does not have to be specified
+     if (backend.size() == 0) {
+         if (backends.size() == 1) {
+@@ -230,11 +235,13 @@
+     }
+     vector<string>::const_iterator b
+         = find(backends.begin(), backends.end(), backend);
++cerr << "n backends: " << backends.size() << endl;
+     if (b == backends.end()) {
+         printBackends("Invalid index type.", backends);
+         return 0;
+     }
+-    return CombinedIndexManager::factories()[backend](indexdir.c_str());
++    return IndexPluginLoader::createIndexManager(backend.c_str(),
++        indexdir.c_str());
+ }
+ int
+ create(int argc, char** argv) {
+@@ -286,7 +293,7 @@
+         analyzer->analyzeDir(j->c_str(), nthreads);
+     }
+     delete analyzer;
+-    delete manager;
++    IndexPluginLoader::deleteIndexManager(manager);
+ 
+     return 0;
+ }
+@@ -329,7 +336,7 @@
+     DirAnalyzer* analyzer = new DirAnalyzer(*manager, config);
+     analyzer->updateDirs(arguments, nthreads);
+     delete analyzer;
+-    delete manager;
++    IndexPluginLoader::deleteIndexManager(manager);
+ 
+     return 0;
+ }
+@@ -363,7 +370,7 @@
+     }
+     IndexReader* reader = manager->indexReader();
+     listFiles(reader, "");
+-    delete manager;
++    IndexPluginLoader::deleteIndexManager(manager);
+     return 0;
+ }
+ int
+@@ -411,7 +418,7 @@
+         }
+     }
+     
+-    delete manager;
++    IndexPluginLoader::deleteIndexManager(manager);
+     return 0;
+ }
+ int
+@@ -478,7 +485,7 @@
+         }
+     }
+     
+-    delete manager;
++    IndexPluginLoader::deleteIndexManager(manager);
+     return 0;
+ }
+ int
+@@ -572,7 +579,7 @@
+     if (results != 0)
+         printf ("Query returned %i results\n", results);
+ 
+-    delete manager;
++    IndexPluginLoader::deleteIndexManager(manager);
+     return 0;
+ }
+ int
+@@ -645,7 +652,7 @@
+         writer->optimize();
+     }
+     
+-    delete manager;
++    IndexPluginLoader::deleteIndexManager(manager);
+     return 0;
+ }
+ int
+@@ -672,7 +679,7 @@
+     for (i=fields.begin(); i!=fields.end(); ++i) {
+         printf("%s\n", i->c_str());
+     }
+-    delete manager;
++    IndexPluginLoader::deleteIndexManager(manager);
+     return 0;
+ }
+ int
+--- a/tests/CMakeLists.txt
++++ b/tests/CMakeLists.txt
+@@ -1,28 +1,21 @@
+-set (TESTINGDIRS ${TESTINGDIRS} utils indextesters streamanalyzer)
++set (TESTINGDIRS utils indextesters streamanalyzer daemon)
++subdirs (${TESTINGDIRS})
++
++# setting for using CPPUNIT
+ 
+-if (CLucene_FOUND OR HyperEstraier_FOUND OR SQLite_FOUND)
+-  set(TESTINGDIRS ${TESTINGDIRS} daemon)
+-endif (CLucene_FOUND OR HyperEstraier_FOUND OR SQLite_FOUND)
++include_directories (. ${CPPUNIT_INCLUDE_DIR}  ${CMAKE_SOURCE_DIR}/src/daemon
++    ${CMAKE_BINARY_DIR}/src/streams)
+ 
+ # cppunit requires exception support
+ IF(NOT WIN32)
+     set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions")
+ ENDIF(NOT WIN32)
+ 
+-# disable, needs some testing
+-#if (HyperEstraier_FOUND)
+-#  set (TESTINGDIRS ${TESTINGDIRS} estraierindexer)
+-#endif (HyperEstraier_FOUND)
+-
+-if (CLucene_FOUND)
+-  set(TESTINGDIRS ${TESTINGDIRS} luceneindexer)
+-endif (CLucene_FOUND)
+-
+-include_directories (. ${CPPUNIT_INCLUDE_DIR} ${strigi_SOURCE_DIR}/src/daemon)
+-
++# a convenience library that adds a unified way of build a test executable
++# for testing
++# simply link this into any unit test executable
+ add_library(test_runner test_runner.cpp)
+ target_link_libraries(test_runner ${CPPUNIT_LIBRARIES})
+ 
+- ENABLE_TESTING()
++ENABLE_TESTING()
+ 
+-subdirs (${TESTINGDIRS})
+--- a/tests/daemon/CMakeLists.txt
++++ b/tests/daemon/CMakeLists.txt
+@@ -1,8 +1,5 @@
+ # add a test for the daemon configuration loading classes
+ 
+-# fancy way of saying set(INC_DIR test/daemon)
+-string(REGEX REPLACE /test /src INC_DIR ${CMAKE_CURRENT_SOURCE_DIR})
+-
+ # if we use log4cxx, include it
+ # ideally this should be abstracted away in something like STRIGILOG( ... )
+ if (ENABLE_LOG4CXX AND Log4cxx_FOUND)
+--- a/tests/estraierindexer/CMakeLists.txt
++++ /dev/null
+@@ -1,26 +0,0 @@
+-STRING(REGEX REPLACE /test /src INC_DIR ${CMAKE_CURRENT_SOURCE_DIR})
+-
+-if (ENABLE_LOG4CXX AND Log4cxx_FOUND)
+-    set(estraiertest_LIBS ${estraiertest_LIBS} ${LOG4CXX_LIBRARIES})
+-    set (INC_DIR ${INC_DIR} ${LOG4CXX_INCLUDE_DIR})
+-    add_definitions(-DHAVE_LOG4CXX)
+-endif (ENABLE_LOG4CXX AND Log4cxx_FOUND)
+-
+-include_directories (. .. ${INC_DIR}
+-                     ../indextests
+-                     ${strigi_SOURCE_DIR}/src/streamanalyzer
+-                     ${strigi_SOURCE_DIR}/src/streams
+-                     ${strigi_BINARY_DIR}/src/streams
+-                     ${strigi_SOURCE_DIR}/src/streams/strigi
+-                     ${EST_INCLUDE_DIR}
+-)
+-
+-add_library(estraiertest SHARED   estraierindexmanagertest.cpp
+-                                ../indextests/indexmanagertester.cpp
+-                                estraierindexreadertest.cpp
+-                                ../indextests/indexreadertester.cpp
+-                                estraierindexwritertest.cpp
+-                                ../indextests/indexwritertester.cpp )
+-
+-target_link_libraries (estraiertest estraierindex ${estraiertest_LIBS})
+-add_test (estraiertest estraiertest)
+--- a/tests/estraierindexer/estraierindexmanagertest.cpp
++++ /dev/null
+@@ -1,72 +0,0 @@
+-/* This file is part of Strigi Desktop Search
+- *
+- * Copyright (C) 2007 Flavio Castelli <flavio.castelli at gmail.com>
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Library General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * Library General Public License for more details.
+- *
+- * You should have received a copy of the GNU Library General Public License
+- * along with this library; see the file COPYING.LIB.  If not, write to
+- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+- * Boston, MA 02110-1301, USA.
+- */
+-#include "estraierindexmanagertest.h"
+-
+-#include "analysisresult.h"
+-#include "analyzerconfiguration.h"
+-#include "estraierindexmanager.h"
+-#include "indexwriter.h"
+-#include "indexreader.h"
+-#include "query.h"
+-
+-#include <string>
+-#include <sstream>
+-#include <sys/stat.h>
+-#include <sys/types.h>
+-#include <stdlib.h>
+-#ifdef _WIN32
+-#include <direct.h>
+-#endif
+-
+-using namespace std;
+-using namespace strigiunittest;
+-
+-// Registers the fixture into the 'registry'
+-CPPUNIT_TEST_SUITE_REGISTRATION( EstraierIndexManagerTest );
+-
+-void EstraierIndexManagerTest::setUp()
+-{
+-    IndexManagerTester::setUp();
+-    
+-    path = "testestraierindex";
+-
+-    // initialize a directory for writing and an indexmanager
+-#ifdef _WIN32
+-    mkdir(path.c_str());
+-#else
+-    mkdir(path.c_str(), S_IRUSR|S_IWUSR|S_IXUSR);
+-#endif
+-
+-    manager = new EstraierIndexManager(path.c_str());
+-    writer = manager->getIndexWriter();
+-    reader = manager->getIndexReader();
+-    ic = new Strigi::AnalyzerConfiguration ();
+-    si = new Strigi::StreamAnalyzer (*ic);
+-}
+-
+-void EstraierIndexManagerTest::tearDown()
+-{
+-    IndexManagerTester::tearDown();
+-    
+-    // clean up data
+-    string cmd = "rm -r ";
+-    cmd += path;
+-    system(cmd.c_str());
+-}
+--- a/tests/estraierindexer/estraierindexmanagertest.h
++++ /dev/null
+@@ -1,43 +0,0 @@
+-/* This file is part of Strigi Desktop Search
+- *
+- * Copyright (C) 2007 Flavio Castelli <flavio.castelli at gmail.com>
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Library General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * Library General Public License for more details.
+- *
+- * You should have received a copy of the GNU Library General Public License
+- * along with this library; see the file COPYING.LIB.  If not, write to
+- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+- * Boston, MA 02110-1301, USA.
+- */
+-#ifndef UNIT_TEST_ESTRAIER_INDEX_MANAGER_TEST_H
+-#define UNIT_TEST_ESTRAIER_INDEX_MANAGER_TEST_H
+-
+-#include "indexmanagertester.h"
+-
+-namespace strigiunittest
+-{
+-    class EstraierIndexManagerTest : public IndexManagerTester
+-    {
+-        CPPUNIT_TEST_SUB_SUITE( EstraierIndexManagerTest,  IndexManagerTester);
+-        CPPUNIT_TEST( testVariables );
+-        //CPPUNIT_TEST( runUnthreadedTests );
+-        //CPPUNIT_TEST( runThreadedTests );
+-        CPPUNIT_TEST( addAndCount );
+-        CPPUNIT_TEST( testNumberQuery );
+-        CPPUNIT_TEST_SUITE_END();
+-        
+-        public:
+-            void setUp();
+-            void tearDown();
+-    };
+-}
+-
+-#endif
+--- a/tests/estraierindexer/estraierindexreadertest.cpp
++++ /dev/null
+@@ -1,69 +0,0 @@
+-/* This file is part of Strigi Desktop Search
+- *
+- * Copyright (C) 2007 Flavio Castelli <flavio.castelli at gmail.com>
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Library General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * Library General Public License for more details.
+- *
+- * You should have received a copy of the GNU Library General Public License
+- * along with this library; see the file COPYING.LIB.  If not, write to
+- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+- * Boston, MA 02110-1301, USA.
+- */
+-#include "estraierindexreadertest.h"
+-
+-#include "analysisresult.h"
+-#include "analyzerconfiguration.h"
+-#include "estraierindexmanager.h"
+-#include "indexwriter.h"
+-#include "indexreader.h"
+-#include "query.h"
+-
+-#include <string>
+-#include <sstream>
+-#include <sys/stat.h>
+-#include <sys/types.h>
+-#include <stdlib.h>
+-#ifdef _WIN32
+-#include <direct.h>
+-#endif
+-
+-using namespace std;
+-using namespace strigiunittest;
+-
+-// Registers the fixture into the 'registry'
+-CPPUNIT_TEST_SUITE_REGISTRATION( EstraierIndexReaderTest );
+-
+-void EstraierIndexReaderTest::setUp()
+-{
+-    IndexReaderTester::setUp();
+-    
+-    path = "testestraier";
+-
+-    // initialize a directory for writing and an indexmanager
+-#ifdef _WIN32
+-    mkdir(path.c_str());
+-#else
+-    mkdir(path.c_str(), S_IRUSR|S_IWUSR|S_IXUSR);
+-#endif
+-
+-    manager = new EstraierIndexManager(path.c_str());
+-    reader = manager->getIndexReader();
+-}
+-
+-void EstraierIndexReaderTest::tearDown()
+-{
+-    IndexReaderTester::tearDown();
+-    
+-    // clean up data
+-    string cmd = "rm -r ";
+-    cmd += path;
+-    system(cmd.c_str());
+-}
+--- a/tests/estraierindexer/estraierindexreadertest.h
++++ /dev/null
+@@ -1,40 +0,0 @@
+-/* This file is part of Strigi Desktop Search
+- *
+- * Copyright (C) 2007 Flavio Castelli <flavio.castelli at gmail.com>
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Library General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * Library General Public License for more details.
+- *
+- * You should have received a copy of the GNU Library General Public License
+- * along with this library; see the file COPYING.LIB.  If not, write to
+- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+- * Boston, MA 02110-1301, USA.
+- */
+-#ifndef UNIT_TEST_ESTRAIER_INDEX_READER_TEST_H
+-#define UNIT_TEST_ESTRAIER_INDEX_READER_TEST_H
+-
+-#include "indexreadertester.h"
+-
+-namespace strigiunittest
+-{
+-    class EstraierIndexReaderTest : public IndexReaderTester
+-    {
+-        CPPUNIT_TEST_SUB_SUITE( EstraierIndexReaderTest,  IndexReaderTester);
+-        CPPUNIT_TEST( testVariables );
+-        CPPUNIT_TEST( getFiles );
+-        CPPUNIT_TEST_SUITE_END();
+-        
+-        public:
+-            void setUp();
+-            void tearDown();
+-    };
+-}
+-
+-#endif
+--- a/tests/estraierindexer/estraierindexwritertest.cpp
++++ /dev/null
+@@ -1,70 +0,0 @@
+-/* This file is part of Strigi Desktop Search
+- *
+- * Copyright (C) 2007 Flavio Castelli <flavio.castelli at gmail.com>
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Library General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * Library General Public License for more details.
+- *
+- * You should have received a copy of the GNU Library General Public License
+- * along with this library; see the file COPYING.LIB.  If not, write to
+- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+- * Boston, MA 02110-1301, USA.
+- */
+-#include "estraierindexwritertest.h"
+-
+-#include "analysisresult.h"
+-#include "analyzerconfiguration.h"
+-#include "estraierindexmanager.h"
+-#include "indexwriter.h"
+-#include "query.h"
+-
+-#include <string>
+-#include <sstream>
+-#include <sys/stat.h>
+-#include <sys/types.h>
+-#include <stdlib.h>
+-#ifdef _WIN32
+-#include <direct.h>
+-#endif
+-
+-using namespace std;
+-using namespace strigiunittest;
+-
+-// Registers the fixture into the 'registry'
+-CPPUNIT_TEST_SUITE_REGISTRATION( EstraierIndexWriterTest );
+-
+-void EstraierIndexWriterTest::setUp()
+-{
+-    IndexWriterTester::setUp();
+-    
+-    path = "testestraierindex";
+-
+-    // initialize a directory for writing and an indexmanager
+-#ifdef _WIN32
+-    mkdir(path.c_str());
+-#else
+-    mkdir(path.c_str(), S_IRUSR|S_IWUSR|S_IXUSR);
+-#endif
+-
+-    manager = new EstraierIndexManager(path.c_str());
+-    writer = manager->getIndexWriter();
+-    ic = new Strigi::AnalyzerConfiguration ();
+-    si = new Strigi::StreamAnalyzer (*ic);
+-}
+-
+-void EstraierIndexWriterTest::tearDown()
+-{
+-    IndexWriterTester::tearDown();
+-    
+-    // clean up data
+-    string cmd = "rm -r ";
+-    cmd += path;
+-    system(cmd.c_str());
+-}
+--- a/tests/estraierindexer/estraierindexwritertest.h
++++ /dev/null
+@@ -1,41 +0,0 @@
+-/* This file is part of Strigi Desktop Search
+- *
+- * Copyright (C) 2007 Flavio Castelli <flavio.castelli at gmail.com>
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Library General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * Library General Public License for more details.
+- *
+- * You should have received a copy of the GNU Library General Public License
+- * along with this library; see the file COPYING.LIB.  If not, write to
+- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+- * Boston, MA 02110-1301, USA.
+- */
+-#ifndef UNIT_TEST_ESTRAIER_INDEX_WRITER_TEST_H
+-#define UNIT_TEST_ESTRAIER_INDEX_WRITER_TEST_H
+-
+-#include "indexwritertester.h"
+-
+-namespace strigiunittest
+-{
+-    class EstraierIndexWriterTest : public IndexWriterTester
+-    {
+-        CPPUNIT_TEST_SUB_SUITE( EstraierIndexWriterTest,  IndexWriterTester);
+-        CPPUNIT_TEST( testVariables );
+-        CPPUNIT_TEST( add );
+-        CPPUNIT_TEST( optimize );
+-        CPPUNIT_TEST_SUITE_END();
+-        
+-        public:
+-            void setUp();
+-            void tearDown();
+-    };
+-}
+-
+-#endif
+--- /dev/null
++++ b/tests/indextesters/clucenetests.cpp
+@@ -0,0 +1,52 @@
++/* This file is part of Strigi Desktop Search
++ *
++ * Copyright (C) 2007 Jos van den Oever <jos at vandenoever.info>
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public License
++ * along with this library; see the file COPYING.LIB.  If not, write to
++ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
++ * Boston, MA 02110-1301, USA.
++ */
++
++#include "indexreadertester.h"
++#include "indexwritertester.h"
++#include "indexsearchtester.h"
++using namespace strigiunittest;
++
++class CLuceneIndexReaderTest : public IndexReaderTest {
++private:
++    CPPUNIT_TEST_SUB_SUITE( CLuceneIndexReaderTest, IndexReaderTest);
++    CPPUNIT_TEST_SUITE_END();
++public:
++    CLuceneIndexReaderTest() :IndexReaderTest("clucene") {}
++};
++CPPUNIT_TEST_SUITE_REGISTRATION( CLuceneIndexReaderTest );
++
++class CLuceneIndexWriterTest : public IndexWriterTest {
++private:
++    CPPUNIT_TEST_SUB_SUITE( CLuceneIndexWriterTest, IndexWriterTest);
++    CPPUNIT_TEST_SUITE_END();
++public:
++    CLuceneIndexWriterTest() :IndexWriterTest("clucene") {}
++};
++CPPUNIT_TEST_SUITE_REGISTRATION( CLuceneIndexWriterTest );
++
++class CLuceneIndexSearchTest : public IndexSearchTest {
++private:
++    CPPUNIT_TEST_SUB_SUITE( CLuceneIndexSearchTest, IndexSearchTest);
++    CPPUNIT_TEST_SUITE_END();
++public:
++    CLuceneIndexSearchTest() :IndexSearchTest("clucene") {}
++};
++CPPUNIT_TEST_SUITE_REGISTRATION( CLuceneIndexSearchTest );
++
+--- a/tests/indextesters/CMakeLists.txt
++++ b/tests/indextesters/CMakeLists.txt
+@@ -1,6 +1,6 @@
+ if (ENABLE_LOG4CXX AND Log4cxx_FOUND)
+-  set(indextesters_LIBS ${indextesters_LIBS} ${LOG4CXX_LIBRARIES})
+-  set (INC_DIR ${INC_DIR} ${LOG4CXX_INCLUDE_DIR})
++  set(indextesters_LIBS ${LOG4CXX_LIBRARIES})
++  set(INC_DIR ${LOG4CXX_INCLUDE_DIR})
+   add_definitions(-DHAVE_LOG4CXX)
+ endif (ENABLE_LOG4CXX AND Log4cxx_FOUND)
+ 
+@@ -12,10 +12,26 @@
+   ../utils
+ )
+ 
+-add_library(indextesters indexmanagertester.cpp
+-                         indexreadertester.cpp
+-                         indexwritertester.cpp
+-                         indexsearchtester.cpp
+-)
++set(indextester_SRCS indextest.cpp indexreadertester.cpp indexwritertester.cpp
++    indexsearchtester.cpp)
++if (CLucene_FOUND)
++  set(indextester_SRCS ${indextester_SRCS} clucenetests.cpp)
++  set (indextester_DEPS ${indextester_DEPS} clucene)
++endif (CLucene_FOUND)
++if (ENABLE_SQLITE AND SQLite_FOUND)
++  set (indextester_SRCS ${indextester_SRCS} sqlitetests.cpp)
++  set (indextester_DEPS sqlite)
++endif (ENABLE_SQLITE AND SQLite_FOUND)
++if (HyperEstraier_FOUND)
++  set (indextester_SRCS ${indextester_SRCS} estraiertests.cpp)
++  set (indextester_DEPS estraier)
++endif (HyperEstraier_FOUND)
++
++add_executable(indextester ${indextester_SRCS})
++if (indextester_DEPS)
++  ADD_DEPENDENCIES(indextester ${indextester_DEPS})
++endif (indextester_DEPS)
++target_link_libraries(indextester
++  test_runner unittestfunctions ${indextesters_LIBS})
+ 
+-target_link_libraries (indextesters unittestfunctions ${indextesters_LIBS})
++add_test(indextester indextester)
+--- /dev/null
++++ b/tests/indextesters/estraiertests.cpp
+@@ -0,0 +1,52 @@
++/* This file is part of Strigi Desktop Search
++ *
++ * Copyright (C) 2007 Jos van den Oever <jos at vandenoever.info>
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public License
++ * along with this library; see the file COPYING.LIB.  If not, write to
++ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
++ * Boston, MA 02110-1301, USA.
++ */
++
++#include "indexreadertester.h"
++#include "indexwritertester.h"
++#include "indexsearchtester.h"
++using namespace strigiunittest;
++
++class EstraierIndexReaderTest : public IndexReaderTest {
++private:
++    CPPUNIT_TEST_SUB_SUITE( EstraierIndexReaderTest, IndexReaderTest);
++    CPPUNIT_TEST_SUITE_END();
++public:
++    EstraierIndexReaderTest() :IndexReaderTest("estraier") {}
++};
++CPPUNIT_TEST_SUITE_REGISTRATION( EstraierIndexReaderTest );
++
++class EstraierIndexWriterTest : public IndexWriterTest {
++private:
++    CPPUNIT_TEST_SUB_SUITE( EstraierIndexWriterTest, IndexWriterTest);
++    CPPUNIT_TEST_SUITE_END();
++public:
++    EstraierIndexWriterTest() :IndexWriterTest("estraier") {}
++};
++CPPUNIT_TEST_SUITE_REGISTRATION( EstraierIndexWriterTest );
++
++
++class EstraierIndexSearchTest : public IndexSearchTest {
++private:
++    CPPUNIT_TEST_SUB_SUITE( EstraierIndexSearchTest, IndexSearchTest);
++    CPPUNIT_TEST_SUITE_END();
++public:
++    EstraierIndexSearchTest() :IndexSearchTest("estraier") {}
++};
++CPPUNIT_TEST_SUITE_REGISTRATION( EstraierIndexSearchTest );
+--- a/tests/indextesters/indexmanagertester.cpp
++++ b/tests/indextesters/indexmanagertester.cpp
+@@ -18,53 +18,41 @@
+  * Boston, MA 02110-1301, USA.
+  */
+ #include "indexmanagertester.h"
+-
+-#include "analysisresult.h"
+-#include "analyzerconfiguration.h"
+ #include "indexmanager.h"
+-#include "indexwriter.h"
+-#include "indexreader.h"
+-#include "fieldtypes.h"
+-#include "query.h"
+-#include "queryparser.h"
+-
+-#include <sstream>
+-#include <sys/stat.h>
+-#include <sys/types.h>
+-#include <stdlib.h>
+-#ifdef _WIN32
+-#include <direct.h>
+-#endif
++#include "indexpluginloader.h"
+ 
+ using namespace std;
+ using namespace Strigi;
+ using namespace strigiunittest;
+ 
+-void IndexManagerTester::setUp()
+-{
+-    m_manager = createManager();
+-}
++CPPUNIT_TEST_SUITE_REGISTRATION( CLuceneIndexManagerTest );
+ 
+-void IndexManagerTester::tearDown()
+-{
+-    deleteManager( m_manager );
++IndexManagerTest::IndexManagerTest(const std::string& backendname)
++    :m_backendname(backendname), m_indexpath(":memory:"), m_manager(0) {
+ }
+ 
+-
+-void IndexManagerTester::deleteManager( Strigi::IndexManager* m )
+-{
+-    delete m;
++void
++IndexManagerTest::setUp() {
++    m_manager = Strigi::IndexPluginLoader::createIndexManager(
++        m_backendname.c_str(), m_indexpath.c_str());
+ }
+ 
++void
++IndexManagerTest::tearDown() {
++    Strigi::IndexPluginLoader::deleteIndexManager(m_manager);
++    // clean up data (if any)
++    string cmd("rm -rf '" + m_indexpath + "'");
++    system(cmd.c_str());
++}
+ 
+-void IndexManagerTester::testIndexReader()
+-{
++void
++IndexManagerTest::testIndexReader() {
+     Strigi::IndexReader* reader = m_manager->indexReader();
+     CPPUNIT_ASSERT_MESSAGE("reader creation failed", reader);
+ }
+ 
+-void IndexManagerTester::testIndexWriter()
+-{
++void
++IndexManagerTest::testIndexWriter() {
+     Strigi::IndexWriter* writer = m_manager->indexWriter();
+     CPPUNIT_ASSERT_MESSAGE("writer creation failed", writer);
+ }
+--- a/tests/indextesters/indexmanagertester.h
++++ b/tests/indextesters/indexmanagertester.h
+@@ -30,34 +30,37 @@
+     class IndexReader;
+ }
+ 
+-namespace strigiunittest
+-{
+-    class IndexManagerTester : public CppUnit::TestFixture
+-    {
+-        CPPUNIT_TEST_SUITE( IndexManagerTester );
+-        CPPUNIT_TEST( testIndexReader );
+-        CPPUNIT_TEST( testIndexWriter );
+-        CPPUNIT_TEST_SUITE_END_ABSTRACT();
+-
+-    private:
+-	Strigi::IndexManager* m_manager;
+-
+-    protected:
+-	virtual Strigi::IndexManager* createManager() = 0;
+-
+-	/**
+-	 * delete the manager. The default implementation simply
+-	 * calls delete.
+-	 */
+-	virtual void deleteManager( Strigi::IndexManager* );
+-        
+-    public:
+-	virtual void setUp();
+-	virtual void tearDown();
+-            
+-	virtual void testIndexReader();
+-	virtual void testIndexWriter();
+-    };
+-}
++namespace strigiunittest {
++
++class IndexManagerTest : public CppUnit::TestFixture {
++private:
++    CPPUNIT_TEST_SUITE( IndexManagerTest );
++    CPPUNIT_TEST( testIndexReader );
++    CPPUNIT_TEST( testIndexWriter );
++    CPPUNIT_TEST_SUITE_END_ABSTRACT();
++
++    const std::string m_backendname;
++    const std::string m_indexpath;
++    Strigi::IndexManager* m_manager;
++
++protected:
++    IndexManagerTest(const std::string& backendname);
+ 
++public:
++    void setUp();
++    void tearDown();
++
++    void testIndexReader();
++    void testIndexWriter();
++};
++
++class CLuceneIndexManagerTest : public IndexManagerTest {
++private:
++    CPPUNIT_TEST_SUB_SUITE( CLuceneIndexManagerTest, IndexManagerTest);
++    CPPUNIT_TEST_SUITE_END();
++public:
++    CLuceneIndexManagerTest() :IndexManagerTest("clucene") {}
++};
++
++}
+ #endif
+--- a/tests/indextesters/indexreadertester.cpp
++++ b/tests/indextesters/indexreadertester.cpp
+@@ -20,61 +20,38 @@
+ #include "indexreadertester.h"
+ 
+ #include "analysisresult.h"
+-#include "analyzerconfiguration.h"
+-#include "indexmanager.h"
+ #include "indexwriter.h"
+ #include "indexreader.h"
+ #include "fieldtypes.h"
+-#include "analyzerconfiguration.h"
+ #include "query.h"
+ #include "queryparser.h"
+ 
+-#include <string>
+ #include <sstream>
+-#include <sys/stat.h>
+-#include <sys/types.h>
+-#include <stdlib.h>
+-#ifdef _WIN32
+-#include <direct.h>
+-#endif
+-
+ #include <ostream>
+ 
+ using namespace std;
+ using namespace strigiunittest;
+ using namespace Strigi;
+ 
+-void IndexReaderTester::setUp()
+-{
+-    m_manager = createManager();
+-    m_writer = m_manager->indexWriter();
+-    m_reader = m_manager->indexReader();
+-
+-    CPPUNIT_ASSERT_MESSAGE("writer creation failed", m_writer);
+-    CPPUNIT_ASSERT_MESSAGE("reader creation failed", m_reader);
+-
++void
++IndexReaderTest::setUp() {
++    IndexTest::setUp();
+     m_streamAnalyzer = new Strigi::StreamAnalyzer( m_analyzerConfiguration );
+ }
+ 
+-void IndexReaderTester::tearDown()
+-{
++void
++IndexReaderTest::tearDown() {
+     delete m_streamAnalyzer;
+-    deleteManager( m_manager );
+-}
+-
+-
+-void IndexReaderTester::deleteManager( Strigi::IndexManager* m )
+-{
+-    delete m;
++    IndexTest::tearDown();
+ }
+ 
+ void
+-IndexReaderTester::testChildrenRetrieval() {
++IndexReaderTest::testChildrenRetrieval() {
+     // FIXME
+ }
+ 
+-void IndexReaderTester::addAndCount()
+-{
++void
++IndexReaderTest::addAndCount() {
+     static const int m = 20;
+ 
+     m_writer->deleteAllEntries();
+@@ -93,8 +70,8 @@
+     CPPUNIT_ASSERT_EQUAL_MESSAGE(str.str(), m, n);
+ }
+ 
+-void IndexReaderTester::testNumberQuery()
+-{
++void
++IndexReaderTest::testNumberQuery() {
+     m_writer->deleteAllEntries();
+     // add numbers to the database
+     int m = 200;
+--- a/tests/indextesters/indexreadertester.h
++++ b/tests/indextesters/indexreadertester.h
+@@ -20,55 +20,37 @@
+ #ifndef UNIT_TEST_INDEX_READER_TESTER_H
+ #define UNIT_TEST_INDEX_READER_TESTER_H
+ 
+-#include <cppunit/TestFixture.h>
+-#include <cppunit/extensions/HelperMacros.h>
+-#include <string>
+-
++#include "indextest.h"
+ #include "analyzerconfiguration.h"
+-#include "fieldtypes.h"
+ 
+ namespace Strigi {
+-    class IndexManager;
+-    class IndexReader;
+-    class IndexWriter;
+     class StreamAnalyzer;
+ }
+ 
+-namespace strigiunittest
+-{
+-    class IndexReaderTester : public CppUnit::TestFixture
+-    {
+-        CPPUNIT_TEST_SUITE( IndexReaderTester );
+-        CPPUNIT_TEST( testChildrenRetrieval );
+-        CPPUNIT_TEST( addAndCount );
+-        CPPUNIT_TEST( testNumberQuery );
+-        CPPUNIT_TEST_SUITE_END_ABSTRACT();
+-        
+-    private:
+-	Strigi::IndexManager* m_manager;
+-
+-	Strigi::IndexWriter* m_writer;
+-	Strigi::IndexReader* m_reader;
+-	Strigi::StreamAnalyzer* m_streamAnalyzer;
+-	Strigi::AnalyzerConfiguration m_analyzerConfiguration;
+-	Strigi::FieldRegister m_fieldRegister;
+-
+-    protected:
+-	virtual Strigi::IndexManager* createManager() = 0;
+-	/**
+-	 * delete the manager. The default implementation simply
+-	 * calls delete.
+-	 */
+-	virtual void deleteManager( Strigi::IndexManager* );
+-
+-    public:
+-	virtual void setUp();
+-	virtual void tearDown();
+-            
+-	virtual void addAndCount();
+-	virtual void testChildrenRetrieval();
+-	virtual void testNumberQuery();
+-    };
++namespace strigiunittest {
++
++class IndexReaderTest : public IndexTest {
++private:
++    CPPUNIT_TEST_SUITE( IndexReaderTest );
++    CPPUNIT_TEST( testChildrenRetrieval );
++    CPPUNIT_TEST( addAndCount );
++    CPPUNIT_TEST( testNumberQuery );
++    CPPUNIT_TEST_SUITE_END_ABSTRACT();
++
++    Strigi::StreamAnalyzer* m_streamAnalyzer;
++    Strigi::AnalyzerConfiguration m_analyzerConfiguration;
++    Strigi::FieldRegister m_fieldRegister;
++
++    void addAndCount();
++    void testChildrenRetrieval();
++    void testNumberQuery();
++public:
++    IndexReaderTest(const std::string& backendname) :IndexTest(backendname),
++        m_streamAnalyzer(0) {}
++    void setUp();
++    void tearDown();
++};
++
+ }
+ 
+ #endif
+--- a/tests/indextesters/indexsearchtester.cpp
++++ b/tests/indextesters/indexsearchtester.cpp
+@@ -27,6 +27,7 @@
+ #include "query.h"
+ #include "queryparser.h"
+ #include "unittestfunctions.h"
++#include "indexpluginloader.h"
+ 
+ #include  <errno.h>
+ #include <fstream>
+@@ -39,23 +40,12 @@
+ using namespace strigiunittest;
+ 
+ void
+-IndexSearchTester::setUp() {
++IndexSearchTest::setUp() {
++    IndexTest::setUp();
++
+     char buff[13];
+     char* dirname;
+     string separator;
+-    
+-    // generate index dir name
+-    strcpy(buff, "strigiXXXXXX");
+-    dirname = mkdtemp(buff);
+-    
+-    if (dirname) {
+-        cout << "created index dir: " << dirname << endl;
+-        indexdir.assign(dirname);
+-    } else {
+-        cerr << "Error creating temporary directory for index because of: "
+-            << strerror(errno) << endl;
+-        return;
+-    }
+ 
+     // generate indexed docs name
+     strcpy(buff, "strigiXXXXXX");
+@@ -68,7 +58,7 @@
+             << strerror(errno) << endl;
+         return;
+     }
+-    
++
+ #ifdef _WIN32
+     separator = "\\";
+ #else
+@@ -78,15 +68,15 @@
+     // prepare files to be indexed
+     string filename;
+     string filecontents;
+-    
++
+     filename = "testfile01";
+     filecontents = "this is a simple test file";
+     indexedFiles.insert(make_pair<string, string> (filename, filecontents));
+-    
++
+     filename = "testfile02";
+     filecontents = "unit testing example";
+     indexedFiles.insert(make_pair<string, string> (filename, filecontents));
+-    
++
+     // create files on file system
+     for (map<string,string>::iterator iter = indexedFiles.begin();
+             iter != indexedFiles.end(); iter++) {
+@@ -100,48 +90,37 @@
+             cerr << "error during creation of file " << fullpath << endl;
+         }
+     }
+-    
+-    manager = getIndexManager(backend, indexdir);
+ 
+-    CPPUNIT_ASSERT_MESSAGE ("manager == null", manager);
+-    
+     Strigi::AnalyzerConfiguration config;
+     Strigi::StreamAnalyzer* streamindexer = new Strigi::StreamAnalyzer(config);
+-    Strigi::IndexWriter* writer = manager->indexWriter();
+-    streamindexer->setIndexWriter(*writer);
+- 
++    streamindexer->setIndexWriter(*m_writer);
++
+     for (map<string,string>::iterator iter = indexedFiles.begin();
+          iter != indexedFiles.end(); iter++) {
+         string temp = filedir + separator + iter->first;
+         fprintf (stderr, "going to index %s\n", temp.c_str());
+         streamindexer->indexFile(temp);
+     }
+-    
++
+     delete streamindexer;
+-    
+-    writer->commit();
+-    
++
++    m_writer->commit();
+ }
+ 
+ void
+-IndexSearchTester::tearDown() {
+-    if (manager)
+-        delete manager;
+-    manager = NULL;
+-    
++IndexSearchTest::tearDown() {
+     // clean up data (does not work on windows)
+-    string cmd = "rm -r " + indexdir + " " + filedir;
++    string cmd = "rm -r '" + filedir + "'";
+     system(cmd.c_str());
++
++    IndexTest::tearDown();
+ }
+ 
+ void
+-IndexSearchTester::testVariables() {
+-    CPPUNIT_ASSERT_MESSAGE ("manager == NULL", manager);
+-    CPPUNIT_ASSERT_MESSAGE ("backend empty", !backend.empty());
+-    CPPUNIT_ASSERT_MESSAGE ("indexdir empty", !indexdir.empty());
++IndexSearchTest::testVariables() {
+     CPPUNIT_ASSERT_MESSAGE ("filedir empty", !filedir.empty());
+-    
+-    unsigned int indexedFilesSize = manager->indexReader()->countDocuments();
++
++    unsigned int indexedFilesSize = m_reader->countDocuments();
+     if (indexedFilesSize != indexedFiles.size()) {
+         ostringstream msg;
+         msg << "There are " << indexedFilesSize << " indexed files instead of "
+@@ -151,30 +130,24 @@
+ }
+ 
+ void
+-IndexSearchTester::testSystemLocationSearchIndexedFile() {
+-    Strigi::IndexReader* reader = manager->indexReader();
+-    CPPUNIT_ASSERT_MESSAGE("reader == NULL", reader);
+-    
++IndexSearchTest::testSystemLocationSearchIndexedFile() {
+     Strigi::QueryParser parser;
+ 
+     Strigi::Query query = parser.buildQuery("name:'testfile01'");
+-    vector<Strigi::IndexedDocument> matches = reader->query(query, 0, 10);
++    vector<Strigi::IndexedDocument> matches = m_reader->query(query, 0, 10);
+ 
+     int nhits = matches.size();
+-    CPPUNIT_ASSERT_EQUAL_MESSAGE("Number of hits is wrong.", nhits, 1);
++    CPPUNIT_ASSERT_EQUAL_MESSAGE("Number of hits is wrong.", 1, nhits);
+ }
+ 
+ void
+-IndexSearchTester::testSystemLocationSearchUnindexedFile() {
+-    Strigi::IndexReader* reader = manager->indexReader();
+-    CPPUNIT_ASSERT_MESSAGE("reader == NULL", reader);
+-
++IndexSearchTest::testSystemLocationSearchUnindexedFile() {
+     Strigi::QueryParser parser;
+ 
+     Strigi::Query query = parser.buildQuery(
+         Strigi::FieldRegister::pathFieldName+":'unindexed'");
+-    vector<Strigi::IndexedDocument> matches = reader->query(query, 0, 10);
++    vector<Strigi::IndexedDocument> matches = m_reader->query(query, 0, 10);
+     int nhits = matches.size();
+-    CPPUNIT_ASSERT_EQUAL_MESSAGE("Number of hits is wrong.", nhits, 0);
++    CPPUNIT_ASSERT_EQUAL_MESSAGE("Number of hits is wrong.", 0, nhits);
+ }
+ 
+--- a/tests/indextesters/indexsearchtester.h
++++ b/tests/indextesters/indexsearchtester.h
+@@ -20,42 +20,33 @@
+ #ifndef UNIT_TEST_INDEX_SEARCH_TESTER_H
+ #define UNIT_TEST_INDEX_SEARCH_TESTER_H
+ 
+-#include <cppunit/TestFixture.h>
+-#include <cppunit/extensions/HelperMacros.h>
++#include "indextest.h"
+ 
+ #include <map>
+-#include <string>
+ 
+-namespace Strigi
+-{
+-    class IndexManager;
+-}
++namespace strigiunittest {
++
++class IndexSearchTest : public IndexTest {
++private:
++    CPPUNIT_TEST_SUITE( IndexSearchTest );
++    CPPUNIT_TEST( testVariables );
++    CPPUNIT_TEST( testSystemLocationSearchIndexedFile );
++    CPPUNIT_TEST( testSystemLocationSearchUnindexedFile );
++    CPPUNIT_TEST_SUITE_END_ABSTRACT();
++
++    std::string filedir;
++    std::map<std::string,std::string> indexedFiles; //!< map with key = file name, and value = file contents
++
++    void testSystemLocationSearchIndexedFile();
++    void testSystemLocationSearchUnindexedFile();
++    void testVariables();
++
++public:
++    IndexSearchTest(const std::string& backendname) :IndexTest(backendname){}
++    void setUp();
++    void tearDown();
++};
+ 
+-namespace strigiunittest
+-{
+-    class IndexSearchTester : public CppUnit::TestFixture
+-    {
+-        CPPUNIT_TEST_SUITE( IndexSearchTester );
+-        CPPUNIT_TEST( testVariables );
+-        CPPUNIT_TEST( testSystemLocationSearchIndexedFile );
+-        CPPUNIT_TEST( testSystemLocationSearchUnindexedFile );
+-        CPPUNIT_TEST_SUITE_END_ABSTRACT();
+-        
+-        protected:
+-            Strigi::IndexManager* manager;
+-            std::string backend;
+-            std::string indexdir;
+-            std::string filedir;
+-            std::map<std::string,std::string> indexedFiles; //!< map with key = file name, and value = file contents
+-            
+-        public:
+-            virtual void setUp();
+-            virtual void tearDown();
+-            
+-            virtual void testSystemLocationSearchIndexedFile();
+-            virtual void testSystemLocationSearchUnindexedFile();
+-            virtual void testVariables();
+-    };
+ }
+ 
+ #endif
+--- /dev/null
++++ b/tests/indextesters/indextest.cpp
+@@ -0,0 +1,52 @@
++/* This file is part of Strigi Desktop Search
++ *
++ * Copyright (C) 2007 Jos van den Oever <jos at vandenoever.info>
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public License
++ * along with this library; see the file COPYING.LIB.  If not, write to
++ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
++ * Boston, MA 02110-1301, USA.
++ */
++#include "indextest.h"
++#include "indexmanager.h"
++#include "indexpluginloader.h"
++
++using namespace std;
++using namespace Strigi;
++using namespace strigiunittest;
++
++IndexTest::IndexTest(const string& backendname, const string& indexpath)
++    :m_backendname(backendname), m_indexpath(":memory:"), m_manager(0) {
++}
++
++void
++IndexTest::setUp() {
++    m_manager = IndexPluginLoader::createIndexManager(
++        m_backendname.c_str(), m_indexpath.c_str());
++    CPPUNIT_ASSERT_MESSAGE("manager creation failed", m_manager);
++    if (!m_manager) return;
++
++    m_writer = m_manager->indexWriter();
++    CPPUNIT_ASSERT_MESSAGE("writer creation failed", m_writer);
++
++    m_reader = m_manager->indexReader();
++    CPPUNIT_ASSERT_MESSAGE("reader creation failed", m_reader);
++}
++
++void
++IndexTest::tearDown() {
++    IndexPluginLoader::deleteIndexManager(m_manager);
++    // clean up data (if any)
++    string cmd("rm -rf '" + m_indexpath + "'");
++    system(cmd.c_str());
++}
+--- /dev/null
++++ b/tests/indextesters/indextest.h
+@@ -0,0 +1,51 @@
++/* This file is part of Strigi Desktop Search
++ *
++ * Copyright (C) 2007 Jos van den Oever <jos at vandenoever.info>
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public License
++ * along with this library; see the file COPYING.LIB.  If not, write to
++ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
++ * Boston, MA 02110-1301, USA.
++ */
++#ifndef UNIT_TEST_INDEX_TEST_H
++#define UNIT_TEST_INDEX_TEST_H
++
++#include <cppunit/TestFixture.h>
++#include <cppunit/extensions/HelperMacros.h>
++#include <string>
++
++namespace Strigi {
++    class IndexManager;
++    class IndexWriter;
++    class IndexReader;
++}
++
++namespace strigiunittest {
++
++class IndexTest : public CppUnit::TestFixture {
++protected:
++    const std::string m_backendname;
++    const std::string m_indexpath;
++    Strigi::IndexManager* m_manager;
++    Strigi::IndexReader* m_reader;
++    Strigi::IndexWriter* m_writer;
++
++    IndexTest(const std::string& backendname,
++        const std::string& indexpath = ":memory:");
++    void setUp();
++    void tearDown();
++};
++
++}
++
++#endif
+--- a/tests/indextesters/indexwritertester.cpp
++++ b/tests/indextesters/indexwritertester.cpp
+@@ -20,55 +20,32 @@
+ #include "indexwritertester.h"
+ 
+ #include "analysisresult.h"
+-#include "analyzerconfiguration.h"
+-#include "indexmanager.h"
+ #include "indexwriter.h"
+ #include "indexreader.h"
+ #include "fieldtypes.h"
+-#include "analyzerconfiguration.h"
+ #include "query.h"
+ #include "queryparser.h"
+ 
+-#include <string>
+ #include <sstream>
+-#include <sys/stat.h>
+-#include <sys/types.h>
+-#include <stdlib.h>
+-#ifdef _WIN32
+-#include <direct.h>
+-#endif
+ 
+ using namespace std;
+ using namespace strigiunittest;
+ using namespace Strigi;
+ 
+-void IndexWriterTester::setUp()
+-{
+-    m_manager = createManager();
+-    m_writer = m_manager->indexWriter();
+-    m_reader = m_manager->indexReader();
+-
+-    CPPUNIT_ASSERT_MESSAGE("writer creation failed", m_writer);
+-    CPPUNIT_ASSERT_MESSAGE("reader creation failed", m_reader);
+-
+-    m_streamAnalyzer = new Strigi::StreamAnalyzer( m_analyzerConfiguration );
++void
++IndexWriterTest::setUp() {
++    IndexTest::setUp();
++    m_streamAnalyzer = new StreamAnalyzer( m_analyzerConfiguration );
+ }
+ 
+-void IndexWriterTester::tearDown()
+-{
++void
++IndexWriterTest::tearDown() {
+     delete m_streamAnalyzer;
+-    deleteManager( m_manager );
+-}
+-
+-
+-void IndexWriterTester::deleteManager( Strigi::IndexManager* m )
+-{
+-    delete m;
++    IndexTest::tearDown();
+ }
+ 
+-
+-void IndexWriterTester::testAddText()
+-{
++void
++IndexWriterTest::testAddText() {
+     // test adding very simple text
+     string path( "/tmp/dummy.txt" );
+     {
+@@ -78,9 +55,12 @@
+     }
+     m_writer->commit();
+ 
+-    std::vector<IndexedDocument> results = m_reader->query( QueryParser::buildQuery("dummy"), 0, 100 );
+-    CPPUNIT_ASSERT_EQUAL_MESSAGE( "got invalid number of results", 1, ( int )results.size() );
+-    CPPUNIT_ASSERT_EQUAL_MESSAGE( "got invalid path result", path, results[0].uri );
++    std::vector<IndexedDocument> results = m_reader->query(
++        QueryParser::buildQuery("dummy"), 0, 100 );
++    CPPUNIT_ASSERT_EQUAL_MESSAGE( "got invalid number of results", 1,
++        (int)results.size() );
++    CPPUNIT_ASSERT_EQUAL_MESSAGE( "got invalid path result", path,
++        results[0].uri );
+ 
+     m_writer->deleteAllEntries();
+ 
+@@ -88,9 +68,8 @@
+ 
+ }
+ 
+-
+-void IndexWriterTester::testDeleteAllEntries()
+-{
++void
++IndexWriterTest::testDeleteAllEntries() {
+     // add some random data
+     string path( "/tmp/dummy.txt" );
+     {
+@@ -107,18 +86,23 @@
+     // now make sure nothing is left
+     std::map<std::string, time_t> children;
+     m_reader->getChildren( std::string(), children );
+-    CPPUNIT_ASSERT_MESSAGE( "Still files left after calling deleteAllEntries.", children.empty() );
++    CPPUNIT_ASSERT_MESSAGE( "Still files left after calling deleteAllEntries.",
++        children.empty() );
+ 
+-    std::vector<IndexedDocument> results = m_reader->query( QueryParser::buildQuery( FieldRegister::pathFieldName + "=\"" + path + "\"" ), 0, 100 );
+-    CPPUNIT_ASSERT_MESSAGE( "Query results not empty after deleteAllEntries", results.empty() );
+-
+-    results = m_reader->query( QueryParser::buildQuery( FieldRegister::filenameFieldName + "=\"dummy.txt\"" ), 0, 100 );
+-    CPPUNIT_ASSERT_MESSAGE( "Query results not empty after deleteAllEntries", results.empty() );
++    std::vector<IndexedDocument> results = m_reader->query(
++        QueryParser::buildQuery(
++            FieldRegister::pathFieldName + "=\"" + path + "\"" ), 0, 100 );
++    CPPUNIT_ASSERT_MESSAGE( "Query results not empty after deleteAllEntries",
++       results.empty() );
++
++    results = m_reader->query( QueryParser::buildQuery(
++        FieldRegister::filenameFieldName + "=\"dummy.txt\"" ), 0, 100 );
++    CPPUNIT_ASSERT_MESSAGE( "Query results not empty after deleteAllEntries",
++        results.empty() );
+ }
+ 
+-
+-void IndexWriterTester::testDeleteEntries()
+-{
++void
++IndexWriterTest::testDeleteEntries() {
+     // add some random data
+     string path1( "/tmp/dummy1.txt" );
+     string path2( "/tmp/dummy2.txt" );
+@@ -128,11 +112,11 @@
+         AnalysisResult anaRes1( path1, 1, *m_writer, *m_streamAnalyzer );
+         AnalysisResult anaRes2( path2, 1, *m_writer, *m_streamAnalyzer );
+ 
+-        m_writer->addValue( &anaRes1, m_fieldRegister.pathField, anaRes1.path() );
+-        m_writer->addValue( &anaRes1, m_fieldRegister.filenameField, filename1 );
++        m_writer->addValue(&anaRes1, m_fieldRegister.pathField, anaRes1.path());
++        m_writer->addValue(&anaRes1, m_fieldRegister.filenameField, filename1);
+ 
+-        m_writer->addValue( &anaRes2, m_fieldRegister.pathField, anaRes2.path() );
+-        m_writer->addValue( &anaRes2, m_fieldRegister.filenameField, filename2 );
++        m_writer->addValue(&anaRes2, m_fieldRegister.pathField, anaRes2.path());
++        m_writer->addValue(&anaRes2, m_fieldRegister.filenameField, filename2 );
+     }
+     m_writer->commit();
+ 
+--- a/tests/indextesters/indexwritertester.h
++++ b/tests/indextesters/indexwritertester.h
+@@ -20,56 +20,40 @@
+ #ifndef UNIT_TEST_INDEX_WRITER_TESTER_H
+ #define UNIT_TEST_INDEX_WRITER_TESTER_H
+ 
+-#include <cppunit/TestFixture.h>
+-#include <cppunit/extensions/HelperMacros.h>
+-#include <string>
++#include "indextest.h"
+ 
+ #include "analyzerconfiguration.h"
+ #include "fieldtypes.h"
+ 
+ namespace Strigi {
+-    class IndexManager;
+-    class IndexWriter;
+-    class IndexReader;
+     class StreamAnalyzer;
+     class AnalysisResult;
+ }
+ 
+-namespace strigiunittest
+-{
+-    class IndexWriterTester : public CppUnit::TestFixture
+-    {
+-        CPPUNIT_TEST_SUITE( IndexWriterTester );
+-        CPPUNIT_TEST( testAddText );
+-        CPPUNIT_TEST( testDeleteAllEntries );
+-
+-        CPPUNIT_TEST_SUITE_END_ABSTRACT();
+-
+-    private:
+-	Strigi::IndexManager* m_manager;
+-
+-	Strigi::IndexWriter* m_writer;
+-	Strigi::IndexReader* m_reader;
+-	Strigi::StreamAnalyzer* m_streamAnalyzer;
+-	Strigi::AnalyzerConfiguration m_analyzerConfiguration;
+-	Strigi::FieldRegister m_fieldRegister;
+-
+-    protected:
+-	virtual Strigi::IndexManager* createManager() = 0;
+-	/**
+-	 * delete the manager. The default implementation simply
+-	 * calls delete.
+-	 */
+-	virtual void deleteManager( Strigi::IndexManager* );
+-                
+-    public:
+-	virtual void setUp();
+-	virtual void tearDown();
+-
+-	void testAddText();
+-	void testDeleteAllEntries();
+-	void testDeleteEntries();
+-    };
++namespace strigiunittest {
++
++class IndexWriterTest : public IndexTest {
++private:
++    CPPUNIT_TEST_SUITE( IndexWriterTest );
++    CPPUNIT_TEST( testAddText );
++    CPPUNIT_TEST( testDeleteAllEntries );
++    CPPUNIT_TEST_SUITE_END_ABSTRACT();
++
++    Strigi::StreamAnalyzer* m_streamAnalyzer;
++    Strigi::AnalyzerConfiguration m_analyzerConfiguration;
++    Strigi::FieldRegister m_fieldRegister;
++
++    void testAddText();
++    void testDeleteAllEntries();
++    void testDeleteEntries();
++
++public:
++    IndexWriterTest(const std::string& backendname) :IndexTest(backendname),
++        m_streamAnalyzer(0) {}
++    void setUp();
++    void tearDown();
++};
++
+ }
+ 
+ #endif
+--- /dev/null
++++ b/tests/indextesters/sqlitetests.cpp
+@@ -0,0 +1,52 @@
++/* This file is part of Strigi Desktop Search
++ *
++ * Copyright (C) 2007 Jos van den Oever <jos at vandenoever.info>
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public License
++ * along with this library; see the file COPYING.LIB.  If not, write to
++ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
++ * Boston, MA 02110-1301, USA.
++ */
++
++#include "indexreadertester.h"
++#include "indexwritertester.h"
++#include "indexsearchtester.h"
++using namespace strigiunittest;
++/*
++class SQLiteIndexReaderTest : public IndexReaderTest {
++private:
++    CPPUNIT_TEST_SUB_SUITE( SQLiteIndexReaderTest, IndexReaderTest);
++    CPPUNIT_TEST_SUITE_END();
++public:
++    SQLiteIndexReaderTest() :IndexReaderTest("sqlite") {}
++};
++CPPUNIT_TEST_SUITE_REGISTRATION( SQLiteIndexReaderTest );
++*/
++class SQLiteIndexWriterTest : public IndexWriterTest {
++private:
++    CPPUNIT_TEST_SUB_SUITE( SQLiteIndexWriterTest, IndexWriterTest);
++    CPPUNIT_TEST_SUITE_END();
++public:
++    SQLiteIndexWriterTest() :IndexWriterTest("sqlite") {}
++};
++CPPUNIT_TEST_SUITE_REGISTRATION( SQLiteIndexWriterTest );
++/*
++
++class SQLiteIndexSearchTest : public IndexSearchTest {
++private:
++    CPPUNIT_TEST_SUB_SUITE( SQLiteIndexSearchTest, IndexSearchTest);
++    CPPUNIT_TEST_SUITE_END();
++public:
++    SQLiteIndexSearchTest() :IndexSearchTest("sqlite") {}
++};
++CPPUNIT_TEST_SUITE_REGISTRATION( SQLiteIndexSearchTest );*/
+--- a/tests/luceneindexer/CMakeLists.txt
++++ /dev/null
+@@ -1,33 +0,0 @@
+-STRING(REGEX REPLACE /test /src INC_DIR ${CMAKE_CURRENT_SOURCE_DIR})
+-
+-if (ENABLE_LOG4CXX AND Log4cxx_FOUND)
+-    set(lucenetest_LIBS ${lucenetest_LIBS} ${LOG4CXX_LIBRARIES})
+-    set (INC_DIR ${INC_DIR} ${LOG4CXX_INCLUDE_DIR})
+-    add_definitions(-DHAVE_LOG4CXX)
+-endif (ENABLE_LOG4CXX AND Log4cxx_FOUND)
+-
+-include_directories (. .. ${INC_DIR}
+-                     ../indextesters
+-                     ../streamanalyzer
+-                     ${strigi_SOURCE_DIR}/src/streamanalyzer
+-                     ${strigi_SOURCE_DIR}/src/luceneindexer
+-                     ${strigi_SOURCE_DIR}/src/streams
+-                     ${strigi_BINARY_DIR}/src/streams
+-                     ${strigi_SOURCE_DIR}/src/streams/strigi
+-                     ${CLUCENE_INCLUDE_DIR}
+-)
+-
+-add_executable (lucenetest  luceneindexmanagertest.cpp
+-                            luceneindexreadertest.cpp
+-                            luceneindexwritertest.cpp
+-                            luceneindexsearchtest.cpp
+-                            lucenediranalyzertest.cpp
+-)
+-
+-target_link_libraries (lucenetest   test_runner
+-                                    streamanalyzertesters
+-                                    indextesters
+-                                    cluceneindex
+-                                    ${lucenetest_LIBS})
+-
+-add_test (lucenetests lucenetest)
+--- a/tests/luceneindexer/lucenediranalyzertest.cpp
++++ /dev/null
+@@ -1,37 +0,0 @@
+-/* This file is part of Strigi Desktop Search
+- *
+- * Copyright (C) 2007 Flavio Castelli <flavio.castelli at gmail.com>
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Library General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * Library General Public License for more details.
+- *
+- * You should have received a copy of the GNU Library General Public License
+- * along with this library; see the file COPYING.LIB.  If not, write to
+- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+- * Boston, MA 02110-1301, USA.
+- */
+-#include "lucenediranalyzertest.h"
+-
+-using namespace std;
+-using namespace strigiunittest;
+-
+-// Registers the fixture into the 'registry'
+-CPPUNIT_TEST_SUITE_REGISTRATION( LuceneDirAnalyzerTest );
+-
+-void LuceneDirAnalyzerTest::setUp()
+-{
+-    backend = "clucene";
+-    DirAnalyzerTester::setUp();
+-}
+-
+-void LuceneDirAnalyzerTest::tearDown()
+-{
+-    DirAnalyzerTester::tearDown();
+-}
+--- a/tests/luceneindexer/lucenediranalyzertest.h
++++ /dev/null
+@@ -1,40 +0,0 @@
+-/* This file is part of Strigi Desktop Search
+- *
+- * Copyright (C) 2007 Flavio Castelli <flavio.castelli at gmail.com>
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Library General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * Library General Public License for more details.
+- *
+- * You should have received a copy of the GNU Library General Public License
+- * along with this library; see the file COPYING.LIB.  If not, write to
+- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+- * Boston, MA 02110-1301, USA.
+- */
+-#ifndef UNIT_TEST_LUCENE_SEARCH_TEST_H
+-#define UNIT_TEST_LUCENE_SEARCH_TEST_H
+-
+-#include "diranalyzertester.h"
+-
+-namespace strigiunittest
+-{
+-    class LuceneDirAnalyzerTest : public DirAnalyzerTester
+-    {
+-        CPPUNIT_TEST_SUB_SUITE( LuceneDirAnalyzerTest,  DirAnalyzerTester);
+-        CPPUNIT_TEST( testVariables );
+-        CPPUNIT_TEST( testCreateIndex );
+-        CPPUNIT_TEST_SUITE_END();
+-        
+-        public:
+-            void setUp();
+-            void tearDown();
+-    };
+-}
+-
+-#endif
+--- a/tests/luceneindexer/luceneindexmanagertest.cpp
++++ /dev/null
+@@ -1,62 +0,0 @@
+-/* This file is part of Strigi Desktop Search
+- *
+- * Copyright (C) 2007 Flavio Castelli <flavio.castelli at gmail.com>
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Library General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * Library General Public License for more details.
+- *
+- * You should have received a copy of the GNU Library General Public License
+- * along with this library; see the file COPYING.LIB.  If not, write to
+- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+- * Boston, MA 02110-1301, USA.
+- */
+-#include "luceneindexmanagertest.h"
+-
+-#include "analysisresult.h"
+-#include "analyzerconfiguration.h"
+-#include "cluceneindexmanager.h"
+-#include "indexwriter.h"
+-#include "indexreader.h"
+-#include "query.h"
+-
+-#include <sys/stat.h>
+-#include <sys/types.h>
+-#include <stdlib.h>
+-#ifdef _WIN32
+-#include <direct.h>
+-#endif
+-
+-using namespace std;
+-using namespace strigiunittest;
+-
+-// Registers the fixture into the 'registry'
+-CPPUNIT_TEST_SUITE_REGISTRATION( LuceneIndexManagerTest );
+-
+-Strigi::IndexManager* LuceneIndexManagerTest::createManager()
+-{
+-    string path = "testcluceneindex";
+-
+-    // initialize a directory for writing and an indexmanager
+-#ifdef _WIN32
+-    mkdir(path.c_str());
+-#else
+-    mkdir(path.c_str(), S_IRUSR|S_IWUSR|S_IXUSR);
+-#endif
+-
+-    return createCLuceneIndexManager(path.c_str());
+-}
+-
+-void LuceneIndexManagerTest::deleteManager( Strigi::IndexManager* m )
+-{
+-    delete m;
+-
+-    // clean up data
+-    system("rm -r testcluceneindex");
+-}
+--- a/tests/luceneindexer/luceneindexmanagertest.h
++++ /dev/null
+@@ -1,38 +0,0 @@
+-/* This file is part of Strigi Desktop Search
+- *
+- * Copyright (C) 2007 Flavio Castelli <flavio.castelli at gmail.com>
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Library General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * Library General Public License for more details.
+- *
+- * You should have received a copy of the GNU Library General Public License
+- * along with this library; see the file COPYING.LIB.  If not, write to
+- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+- * Boston, MA 02110-1301, USA.
+- */
+-#ifndef UNIT_TEST_LUCENE_INDEX_MANAGER_TEST_H
+-#define UNIT_TEST_LUCENE_INDEX_MANAGER_TEST_H
+-
+-#include "indexmanagertester.h"
+-
+-namespace strigiunittest
+-{
+-    class LuceneIndexManagerTest : public IndexManagerTester
+-    {
+-        CPPUNIT_TEST_SUB_SUITE( LuceneIndexManagerTest, IndexManagerTester);
+-        CPPUNIT_TEST_SUITE_END();
+-
+-    private:
+-	Strigi::IndexManager* createManager();
+-	void deleteManager( Strigi::IndexManager* );
+-    };
+-}
+-
+-#endif
+--- a/tests/luceneindexer/luceneindexreadertest.cpp
++++ /dev/null
+@@ -1,64 +0,0 @@
+-/* This file is part of Strigi Desktop Search
+- *
+- * Copyright (C) 2007 Flavio Castelli <flavio.castelli at gmail.com>
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Library General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * Library General Public License for more details.
+- *
+- * You should have received a copy of the GNU Library General Public License
+- * along with this library; see the file COPYING.LIB.  If not, write to
+- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+- * Boston, MA 02110-1301, USA.
+- */
+-#include "luceneindexreadertest.h"
+-
+-#include "analysisresult.h"
+-#include "analyzerconfiguration.h"
+-#include "cluceneindexmanager.h"
+-#include "indexwriter.h"
+-#include "indexreader.h"
+-#include "query.h"
+-
+-#include <string>
+-#include <sstream>
+-#include <sys/stat.h>
+-#include <sys/types.h>
+-#include <stdlib.h>
+-#ifdef _WIN32
+-#include <direct.h>
+-#endif
+-
+-using namespace std;
+-using namespace strigiunittest;
+-
+-// Registers the fixture into the 'registry'
+-CPPUNIT_TEST_SUITE_REGISTRATION( LuceneIndexReaderTest );
+-
+-Strigi::IndexManager* LuceneIndexReaderTest::createManager()
+-{
+-    string path = "testcluceneindex";
+-
+-    // initialize a directory for writing and an indexmanager
+-#ifdef _WIN32
+-    mkdir(path.c_str());
+-#else
+-    mkdir(path.c_str(), S_IRUSR|S_IWUSR|S_IXUSR);
+-#endif
+-
+-    return createCLuceneIndexManager(path.c_str());
+-}
+-
+-void LuceneIndexReaderTest::deleteManager( Strigi::IndexManager* m )
+-{
+-    delete m;
+-
+-    // clean up data
+-    system("rm -r testcluceneindex");
+-}
+--- a/tests/luceneindexer/luceneindexreadertest.h
++++ /dev/null
+@@ -1,38 +0,0 @@
+-/* This file is part of Strigi Desktop Search
+- *
+- * Copyright (C) 2007 Flavio Castelli <flavio.castelli at gmail.com>
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Library General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * Library General Public License for more details.
+- *
+- * You should have received a copy of the GNU Library General Public License
+- * along with this library; see the file COPYING.LIB.  If not, write to
+- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+- * Boston, MA 02110-1301, USA.
+- */
+-#ifndef UNIT_TEST_LUCENE_INDEX_READER_TEST_H
+-#define UNIT_TEST_LUCENE_INDEX_READER_TEST_H
+-
+-#include "indexreadertester.h"
+-
+-namespace strigiunittest
+-{
+-    class LuceneIndexReaderTest : public IndexReaderTester
+-    {
+-        CPPUNIT_TEST_SUB_SUITE( LuceneIndexReaderTest,  IndexReaderTester);
+-        CPPUNIT_TEST_SUITE_END();
+-        
+-    private:
+-	Strigi::IndexManager* createManager();
+-	void deleteManager( Strigi::IndexManager* );
+-    };
+-}
+-
+-#endif
+--- a/tests/luceneindexer/luceneindexsearchtest.cpp
++++ /dev/null
+@@ -1,37 +0,0 @@
+-/* This file is part of Strigi Desktop Search
+- *
+- * Copyright (C) 2007 Flavio Castelli <flavio.castelli at gmail.com>
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Library General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * Library General Public License for more details.
+- *
+- * You should have received a copy of the GNU Library General Public License
+- * along with this library; see the file COPYING.LIB.  If not, write to
+- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+- * Boston, MA 02110-1301, USA.
+- */
+-#include "luceneindexsearchtest.h"
+-
+-using namespace std;
+-using namespace strigiunittest;
+-
+-// Registers the fixture into the 'registry'
+-CPPUNIT_TEST_SUITE_REGISTRATION( LuceneIndexSearchTest );
+-
+-void LuceneIndexSearchTest::setUp()
+-{
+-    backend = "clucene";
+-    IndexSearchTester::setUp();
+-}
+-
+-void LuceneIndexSearchTest::tearDown()
+-{
+-    IndexSearchTester::tearDown();
+-}
+--- a/tests/luceneindexer/luceneindexsearchtest.h
++++ /dev/null
+@@ -1,41 +0,0 @@
+-/* This file is part of Strigi Desktop Search
+- *
+- * Copyright (C) 2007 Flavio Castelli <flavio.castelli at gmail.com>
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Library General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * Library General Public License for more details.
+- *
+- * You should have received a copy of the GNU Library General Public License
+- * along with this library; see the file COPYING.LIB.  If not, write to
+- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+- * Boston, MA 02110-1301, USA.
+- */
+-#ifndef UNIT_TEST_LUCENE_SEARCH_TEST_H
+-#define UNIT_TEST_LUCENE_SEARCH_TEST_H
+-
+-#include "indexsearchtester.h"
+-
+-namespace strigiunittest
+-{
+-    class LuceneIndexSearchTest : public IndexSearchTester
+-    {
+-        CPPUNIT_TEST_SUB_SUITE( LuceneIndexSearchTest,  IndexSearchTester);
+-        CPPUNIT_TEST( testVariables );
+-        CPPUNIT_TEST( testSystemLocationSearchIndexedFile );
+-        CPPUNIT_TEST( testSystemLocationSearchUnindexedFile );
+-        CPPUNIT_TEST_SUITE_END();
+-        
+-        public:
+-            void setUp();
+-            void tearDown();
+-    };
+-}
+-
+-#endif
+--- a/tests/luceneindexer/luceneindexwritertest.cpp
++++ /dev/null
+@@ -1,63 +0,0 @@
+-/* This file is part of Strigi Desktop Search
+- *
+- * Copyright (C) 2007 Flavio Castelli <flavio.castelli at gmail.com>
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Library General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * Library General Public License for more details.
+- *
+- * You should have received a copy of the GNU Library General Public License
+- * along with this library; see the file COPYING.LIB.  If not, write to
+- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+- * Boston, MA 02110-1301, USA.
+- */
+-#include "luceneindexwritertest.h"
+-
+-#include "analysisresult.h"
+-#include "analyzerconfiguration.h"
+-#include "cluceneindexmanager.h"
+-#include "indexwriter.h"
+-#include "query.h"
+-
+-#include <string>
+-#include <sstream>
+-#include <sys/stat.h>
+-#include <sys/types.h>
+-#include <stdlib.h>
+-#ifdef _WIN32
+-#include <direct.h>
+-#endif
+-
+-using namespace std;
+-using namespace strigiunittest;
+-
+-// Registers the fixture into the 'registry'
+-CPPUNIT_TEST_SUITE_REGISTRATION( LuceneIndexWriterTest );
+-
+-Strigi::IndexManager* LuceneIndexWriterTest::createManager()
+-{
+-    string path = "testcluceneindex";
+-
+-    // initialize a directory for writing and an indexmanager
+-#ifdef _WIN32
+-    mkdir(path.c_str());
+-#else
+-    mkdir(path.c_str(), S_IRUSR|S_IWUSR|S_IXUSR);
+-#endif
+-
+-    return createCLuceneIndexManager(path.c_str());
+-}
+-
+-void LuceneIndexWriterTest::deleteManager( Strigi::IndexManager* m )
+-{
+-    delete m;
+-
+-    // clean up data
+-    system("rm -r testcluceneindex");
+-}
+--- a/tests/luceneindexer/luceneindexwritertest.h
++++ /dev/null
+@@ -1,38 +0,0 @@
+-/* This file is part of Strigi Desktop Search
+- *
+- * Copyright (C) 2007 Flavio Castelli <flavio.castelli at gmail.com>
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Library General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+- * Library General Public License for more details.
+- *
+- * You should have received a copy of the GNU Library General Public License
+- * along with this library; see the file COPYING.LIB.  If not, write to
+- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+- * Boston, MA 02110-1301, USA.
+- */
+-#ifndef UNIT_TEST_LUCENE_INDEX_WRITER_TEST_H
+-#define UNIT_TEST_LUCENE_INDEX_WRITER_TEST_H
+-
+-#include "indexwritertester.h"
+-
+-namespace strigiunittest
+-{
+-    class LuceneIndexWriterTest : public IndexWriterTester
+-    {
+-        CPPUNIT_TEST_SUB_SUITE( LuceneIndexWriterTest, IndexWriterTester);
+-        CPPUNIT_TEST_SUITE_END();
+-        
+-    private:
+-	Strigi::IndexManager* createManager();
+-	void deleteManager( Strigi::IndexManager* );
+-    };
+-}
+-
+-#endif
+--- a/tests/streamanalyzer/diranalyzertester.cpp
++++ b/tests/streamanalyzer/diranalyzertester.cpp
+@@ -23,6 +23,7 @@
+ #include "diranalyzer.h"
+ #include "indexmanager.h"
+ #include "indexreader.h"
++#include "indexpluginloader.h"
+ #include "unittestfunctions.h"
+ 
+ #include <errno.h>
+@@ -105,8 +106,9 @@
+ 
+ void DirAnalyzerTester::tearDown()
+ {
+-    if (manager)
+-        delete manager;
++    if (manager) {
++        Strigi::IndexPluginLoader::deleteIndexManager(manager);
++    }
+     manager = NULL;
+ 
+     // clean up data
+--- a/tests/test_runner.cpp
++++ b/tests/test_runner.cpp
+@@ -24,11 +24,27 @@
+ #include <cppunit/TextTestRunner.h>
+ 
+ #include "strigilogging.h"
++#include "config.h"
++
++#include <iostream>
++using namespace std;
++
++int main() {
++    // set some environment variables so that the system can find the desired
++    // files
++    setenv("XDG_DATA_HOME",
++        SOURCEDIR"/src/streamanalyzer/fieldproperties", 1);
++    setenv("XDG_DATA_DIRS",
++        SOURCEDIR"/src/streamanalyzer/fieldproperties", 1);
++    setenv("STRIGI_PLUGIN_PATH",
++        BINARYDIR"/src/luceneindexer/:"
++        BINARYDIR"/src/estraierindexer:"
++        BINARYDIR"/src/sqliteindexer", 1);
++
++cerr << BINARYDIR << endl;
+ 
+-int main()
+-{
+     STRIGI_LOG_INIT_BASIC()
+-    
++
+     // Get the top level suite from the registry
+     CppUnit::Test *suite = CppUnit::TestFactoryRegistry::getRegistry().makeTest();
+ 
+@@ -46,18 +62,3 @@
+     return wasSucessful ? 0 : 1;
+ }
+ 
+-// using namespace CppUnit;
+-// 
+-// int main (int argc, char* argv[]) {
+-//     TextTestRunner runner;
+-//     TestFactoryRegistry& registry = TestFactoryRegistry::getRegistry();
+-// 
+-//      // run all tests if none specified on command line
+-//     Test* test_to_run = registry.makeTest();
+-//     if (argc>1)
+-//         test_to_run = test_to_run->findTest(argv[1]);
+-// 
+-//     runner.addTest( test_to_run );
+-//     bool failed = runner.run("", false);
+-//     return !failed;
+-// }
+--- a/tests/utils/CMakeLists.txt
++++ b/tests/utils/CMakeLists.txt
+@@ -1,8 +1,9 @@
+ include_directories (   .
++                        ${strigi_BINARY_DIR}/src/streams
+                         ${strigi_SOURCE_DIR}/src/streamanalyzer
+                         ${strigi_SOURCE_DIR}/src/combinedindexer
+                     )
+ 
+ add_library(unittestfunctions unittestfunctions.cpp)
+ 
+-target_link_libraries (unittestfunctions combinedindex)
+\ No newline at end of file
++target_link_libraries (unittestfunctions combinedindex)
+--- a/tests/utils/unittestfunctions.cpp
++++ b/tests/utils/unittestfunctions.cpp
+@@ -21,22 +21,14 @@
+ #include "unittestfunctions.h"
+ 
+ #include "indexmanager.h"
+-#include "combinedindexmanager.h"
++#include "indexpluginloader.h"
+ #include <vector>
+ #include <algorithm>
+ 
+ using namespace std;
+ 
+ Strigi::IndexManager* strigiunittest::getIndexManager(string& backend,
+-                                                      const string& indexdir)
+-{
+-    // check arguments: backend
+-    const vector<string>& backends = CombinedIndexManager::backEnds();
+-
+-    vector<string>::const_iterator b
+-            = find(backends.begin(), backends.end(), backend);
+-    if (b == backends.end())
+-        return 0;
+-
+-    return CombinedIndexManager::factories()[backend](indexdir.c_str());
++                                                      const string& indexdir) {
++    return Strigi::IndexPluginLoader::createIndexManager(backend.c_str(),
++        indexdir.c_str());
+ }




More information about the pkg-kde-commits mailing list