Index: src/main/java/com/xpn/xwiki/plugin/lucene/IndexRebuilder.java
===================================================================
--- src/main/java/com/xpn/xwiki/plugin/lucene/IndexRebuilder.java	(revision 13939)
+++ src/main/java/com/xpn/xwiki/plugin/lucene/IndexRebuilder.java	(working copy)
@@ -84,16 +84,28 @@
     /** Variable used for indicating that a rebuild is already in progress. */
     private boolean rebuildInProgress = false;
 
+    /** sql query to reindex with */
+    private String sql = null;
+
+    /** clear index before rebuilding */
+    private boolean clearIndex = false;
+
+    /** only index if the page is not in the index */
+    private boolean refresh = false;
+
+    /** documents currently being checked **/
+    private long tocheck = 0;
+    
     public IndexRebuilder(IndexUpdater indexUpdater, XWikiContext context)
     {
         this.indexUpdater = indexUpdater;
         if (indexUpdater.needInitialBuild) {
-            this.startRebuildIndex(context);
+            this.startRebuildIndex(null, false, false, context);
             LOG.info("Launched initial lucene indexing");
         }
     }
 
-    public synchronized int startRebuildIndex(XWikiContext context)
+    public synchronized int startRebuildIndex(String sql, boolean clearIndex, boolean refresh, XWikiContext context)
     {
         if (rebuildInProgress) {
             LOG.warn("Cannot launch rebuild because a build is in progress");
@@ -101,6 +113,10 @@
         } else {
             this.rebuildInProgress = true;
             this.context = context;
+            this.sql = sql;
+            this.clearIndex = clearIndex;
+            this.refresh = refresh;
+            
             Thread indexRebuilderThread = new Thread(this, "Lucene Index Rebuilder");
             // The JVM should be allowed to shutdown while this thread is running
             indexRebuilderThread.setDaemon(true);
@@ -184,7 +200,10 @@
      */
     private int rebuildIndex(XWikiContext context)
     {
-        this.indexUpdater.cleanIndex();
+        // only clear index if it is asked
+        if (this.clearIndex)
+         this.indexUpdater.cleanIndex();
+
         int retval = 0;
         Collection<String> wikiServers;
         XWiki xwiki = context.getWiki();
@@ -213,6 +232,10 @@
         return retval;
     }
 
+    public long getPreIndexQueueSize() {
+        return tocheck;
+    }
+
     /**
      * Adds the content of a given wiki to the indexUpdater's queue.
      * 
@@ -232,14 +255,32 @@
             context.setDatabase(wikiName);
             Collection<String> docNames = null;
             try {
-                docNames = xwiki.getStore().searchDocumentsNames("", context);
+                docNames = xwiki.getStore().searchDocumentsNames((this.sql!=null) ? this.sql : "", context);
             } catch (XWikiException ex) {
                 LOG.warn(String.format(
                     "Error getting document names for wiki [%s]. Internal error is: $s",
                     wikiName, ex.getMessage()));
                 return -1;
             }
+
+            // update to check size
+            tocheck = (docNames==null) ? 0 : docNames.size();
+
             for (String docName : docNames) {
+                tocheck--;
+                
+                if (refresh) {
+                    // we should check if the page exists in the index
+                    if (this.indexUpdater.isIndexed(wikiName, docName))  {
+                        if (LOG.isDebugEnabled())
+                         LOG.debug("bypassing document " + wikiName + ":" + docName);
+                        continue;
+                    }
+                }
+
+                if (LOG.isDebugEnabled())
+                    LOG.debug("indexing document " + wikiName + ":" + docName);
+
                 XWikiDocument document;
                 try {
                     document = xwiki.getDocument(docName, context);
Index: src/main/java/com/xpn/xwiki/plugin/lucene/LucenePluginApi.java
===================================================================
--- src/main/java/com/xpn/xwiki/plugin/lucene/LucenePluginApi.java	(revision 13939)
+++ src/main/java/com/xpn/xwiki/plugin/lucene/LucenePluginApi.java	(working copy)
@@ -23,7 +23,11 @@
 import org.apache.commons.logging.LogFactory;
 
 import com.xpn.xwiki.XWikiContext;
+import com.xpn.xwiki.doc.XWikiDocument;
+import com.xpn.xwiki.doc.XWikiAttachment;
 import com.xpn.xwiki.api.Context;
+import com.xpn.xwiki.api.Document;
+import com.xpn.xwiki.api.Attachment;
 import com.xpn.xwiki.plugin.PluginApi;
 
 /**
@@ -73,7 +77,7 @@
 
     /**
      * Starts a rebuild of the whole index.
-     * 
+     *
      * @param wiki
      * @param context
      * @return Number of documents scheduled for indexing. -1 in case of errors
@@ -88,6 +92,75 @@
     }
 
     /**
+     * Starts a rebuild of the whole index.
+     *
+     * @return Number of documents scheduled for indexing. -1 in case of errors
+     */
+    public int rebuildIndex(boolean clearIndex)
+    {
+        if (hasAdminRights()) {
+            return getProtectedPlugin().rebuildIndex(clearIndex, false, context);
+        }
+        return REBUILD_NOT_ALLOWED;
+    }
+
+    /**
+     * Starts a rebuild of the whole index.
+     *
+     * @return Number of documents scheduled for indexing. -1 in case of errors
+     */
+    public int rebuildIndex(boolean clearIndex, boolean refresh)
+    {
+        if (hasAdminRights()) {
+            return getProtectedPlugin().rebuildIndex(clearIndex, refresh, context);
+        }
+        return REBUILD_NOT_ALLOWED;
+    }
+
+
+    /**
+     * Starts a rebuild of the whole index.
+     *
+     * @return Number of documents scheduled for indexing. -1 in case of errors
+     */
+    public int reindexFromQuery(String sql, boolean clearIndex, boolean refresh)
+    {
+        if (hasAdminRights()) {
+            return getProtectedPlugin().reindexFromQuery(sql, clearIndex, refresh, context);
+        }
+        return REBUILD_NOT_ALLOWED;
+    }
+
+
+    public int queueDocument(Document doc, XWikiContext context)
+    {
+        if (hasAdminRights()) {
+            getProtectedPlugin().queueDocument(doc.getDocument(), context);
+            getProtectedPlugin().queueAttachment(doc.getDocument(), context);
+            return 1;
+        }
+        return REBUILD_NOT_ALLOWED;
+    }
+
+    public int queueAttachment(Document doc, Attachment attach, XWikiContext context)
+    {
+        if (hasAdminRights()) {
+            getProtectedPlugin().queueAttachment(doc.getDocument(), attach.getAttachment(), context);
+            return 1;
+        }
+        return REBUILD_NOT_ALLOWED;
+    }
+
+    public int queueAttachment(Document doc, XWikiContext context)
+    {
+        if (hasAdminRights()) {
+            getProtectedPlugin().queueAttachment(doc.getDocument(), context);
+            return 1;
+        }
+        return REBUILD_NOT_ALLOWED;
+    }
+
+    /**
      * Searches the named indexes using the given query for documents in the given languages
      * 
      * @param query the query entered by the user
@@ -199,6 +272,11 @@
         return getProtectedPlugin().getLuceneDocCount();
     }
 
+    public long getPreIndexQueueSize()
+    {
+        return getProtectedPlugin().getPreIndexQueueSize();       
+    }
+
     /**
      * Searches the named indexes using the given query for documents in the given languages
      * 
Index: src/main/java/com/xpn/xwiki/plugin/lucene/LucenePlugin.java
===================================================================
--- src/main/java/com/xpn/xwiki/plugin/lucene/LucenePlugin.java	(revision 13939)
+++ src/main/java/com/xpn/xwiki/plugin/lucene/LucenePlugin.java	(working copy)
@@ -145,9 +145,19 @@
 
     public synchronized int rebuildIndex(XWikiContext context)
     {
-        return indexRebuilder.startRebuildIndex(context);
+        return indexRebuilder.startRebuildIndex(null, true, false, context);
     }
 
+    public synchronized int rebuildIndex(boolean clearIndex, boolean refresh, XWikiContext context)
+    {
+        return indexRebuilder.startRebuildIndex(null, clearIndex, refresh, context);
+    }
+
+    public synchronized int reindexFromQuery(String sql, boolean clearIndex, boolean refresh, XWikiContext context)
+    {
+        return indexRebuilder.startRebuildIndex(sql, clearIndex, refresh, context);
+    }
+
     /**
      * Allows to search special named lucene indexes without having to configure them in
      * <tt>xwiki.cfg</tt>. Slower than
@@ -639,4 +649,8 @@
     {
         return indexUpdater.getActiveQueueSize();
     }
+
+    public long getPreIndexQueueSize() {
+        return (indexRebuilder==null) ? 0 : indexRebuilder.getPreIndexQueueSize();
+    }
 }
Index: src/main/java/com/xpn/xwiki/plugin/lucene/IndexUpdater.java
===================================================================
--- src/main/java/com/xpn/xwiki/plugin/lucene/IndexUpdater.java	(revision 13939)
+++ src/main/java/com/xpn/xwiki/plugin/lucene/IndexUpdater.java	(working copy)
@@ -34,12 +34,13 @@
 import org.apache.log4j.MDC;
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.Document;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriter;
-import org.apache.lucene.search.Hits;
-import org.apache.lucene.search.IndexSearcher;
-import org.apache.lucene.search.Query;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.search.*;
 import org.apache.lucene.store.FSDirectory;
+import org.apache.lucene.queryParser.QueryParser;
 
 import com.xpn.xwiki.XWiki;
 import com.xpn.xwiki.XWikiContext;
@@ -146,7 +147,7 @@
                     openSearcher();
                     while (!this.queue.isEmpty()) {
                         IndexData data = this.queue.remove();
-                        List<Integer> oldDocs = getOldIndexDocIds(data);
+                        List<Integer> oldDocs = (data==null) ? null : getOldIndexDocIds(data);
                         if (oldDocs != null) {
                             for (Integer id : oldDocs) {
                                 if (LOG.isDebugEnabled()) {
@@ -579,8 +580,16 @@
     {
         if (writer != null)
             return writer.docCount();
-
-        return -1;
+        else {
+            try {
+                openWriter(false);
+                return writer.docCount();
+            } catch (Exception e) {
+                return -1;
+            } finally {
+                closeWriter();
+            }
+        }
     }
 
     /**
@@ -590,4 +599,46 @@
     {
         return this.activesIndexedDocs;
     }
+
+    public boolean isIndexed(String wiki, String pagename) {
+        try {
+            openSearcher();
+            QueryParser qp = new QueryParser(IndexFields.DOCUMENT_FULLNAME, analyzer);
+            Query query = qp.parse(pagename);
+            Hits hits = searcher.search(query);
+
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("search for document " + pagename + " in wiki " + wiki + " returned " + hits.length() + " hits");
+            }
+            if (hits==null || hits.length()==0)  {
+                if (LOG.isDebugEnabled()) {
+                    LOG.debug("document " + pagename + " in wiki " + wiki + " is not indexed");
+                }
+                return false;
+            }
+
+            Iterator it = hits.iterator();
+            while (it.hasNext()) {
+                Hit hit = (Hit) it.next();
+                Document doc = hit.getDocument();
+                if (wiki.equals(doc.get(IndexFields.DOCUMENT_WIKI))&&pagename.equals(doc.get(IndexFields.DOCUMENT_FULLNAME))) {
+                    if (LOG.isDebugEnabled()) {
+                        LOG.debug("document " + pagename + " in wiki " + wiki + " is already indexed");
+                    }
+                    return true;
+                }
+            }
+            if (LOG.isErrorEnabled()) {
+                LOG.error("document " + pagename + " in wiki " + wiki + " was not found in search result");
+            }
+            return false;
+        } catch (Exception e) {
+            if (LOG.isErrorEnabled()) {
+                LOG.debug("error checking if document " + pagename + " in wiki " + wiki + " is indexed", e);
+            }
+            return false;
+        } finally {
+            closeSearcher();
+        }
+    }
 }
