Scarab commit: svn commit: r10486 - trunk: . build src/conf/classes src/conf/conf src/java/org/tigris/scarab/actions/admin src/java/org/tigris/scarab/attribute src/java/org/tigris/scarab/om src/java/org/tigris/scarab/tools src/java/org/tigris/scarab/tools/localization src/java/org/tigris/scarab/util/word src/test/org/tigris/scarab/util/word src/webapp/WEB-INF/templates/screens/admin www/repository/lucene/jars xdocs

[email protected]
Newsgroups gmane.comp.java.scarab.cvs
Message-ID <[email protected]>
Author: ronvoe122
Date: 2007-12-04 08:00:13-0800
New Revision: 10486

Added:
   trunk/www/repository/lucene/jars/lucene-analyzers-2.2.0.jar   (contents, props changed)
   trunk/www/repository/lucene/jars/lucene-core-2.2.0.jar   (contents, props changed)
Removed:
   trunk/src/java/org/tigris/scarab/util/word/SearchIndex.java
   trunk/www/repository/lucene/jars/lucene-1.2.jar
Modified:
   trunk/build/build.xml
   trunk/project.properties
   trunk/project.xml
   trunk/src/conf/classes/ScarabBundle_de.properties
   trunk/src/conf/classes/ScarabBundle_en.properties
   trunk/src/conf/classes/ScarabBundle_es.properties
   trunk/src/conf/classes/ScarabBundle_fr.properties
   trunk/src/conf/classes/ScarabBundle_it.properties
   trunk/src/conf/classes/ScarabBundle_ja.properties
   trunk/src/conf/classes/ScarabBundle_ko.properties
   trunk/src/conf/classes/ScarabBundle_nl.properties
   trunk/src/conf/classes/ScarabBundle_pl.properties
   trunk/src/conf/classes/ScarabBundle_pt_BR.properties
   trunk/src/conf/classes/ScarabBundle_ru.properties
   trunk/src/conf/classes/ScarabBundle_zh_CN.properties
   trunk/src/conf/classes/ScarabBundle_zh_TW.properties
   trunk/src/conf/conf/componentConfiguration.xml
   trunk/src/conf/conf/componentRoles.xml
   trunk/src/java/org/tigris/scarab/actions/admin/UpdateSearchIndex.java
   trunk/src/java/org/tigris/scarab/attribute/StringAttribute.java
   trunk/src/java/org/tigris/scarab/om/Attachment.java
   trunk/src/java/org/tigris/scarab/om/Issue.java
   trunk/src/java/org/tigris/scarab/tools/ScarabRequestTool.java
   trunk/src/java/org/tigris/scarab/tools/localization/L10NKeySet.java
   trunk/src/java/org/tigris/scarab/util/word/IssueSearch.java
   trunk/src/java/org/tigris/scarab/util/word/LuceneSearchIndex.java
   trunk/src/java/org/tigris/scarab/util/word/PorterStemAnalyzer.java
   trunk/src/java/org/tigris/scarab/util/word/SearchFactory.java
   trunk/src/test/org/tigris/scarab/util/word/LuceneSearchIndexTest.java
   trunk/src/webapp/WEB-INF/templates/screens/admin/UpdateSearchIndex.vm
   trunk/xdocs/scarab_properties.xml

Log:
SCB2413:
* upgraded Lucene to version 2.2.0
* refactored text search 
  (ATTENTION: an existing Lucene-index must be deleted and rebuilt!)
* to improve the search results for non-English text,
  the Analyzer used by Lucene can now be changed in the Scarab.properties
* improved performance of indexing
* re-indexing can now be canceled



Modified: trunk/build/build.xml
Url: http://scarab.tigris.org/source/browse/scarab/trunk/build/build.xml?view=diff&rev=10486&p1=trunk/build/build.xml&p2=trunk/build/build.xml&r1=10485&r2=10486
==============================================================================
--- trunk/build/build.xml	(original)
+++ trunk/build/build.xml	2007-12-04 08:00:13-0800
@@ -165,7 +165,6 @@
                  <include name="**/*.*"/>
              </fileset>
              <filterset>
-                 <filter token="SEARCH_INDEX_PATH" value="${searchindex.path}"/>
                  <filter token="SCARAB_MODULE_CODE_LENGTH" value="${scarab.module.code.length}"/>
                  <filter token="VERSION" value="${version}"/>
                  <filter token="BUILD_DATE" value="${DSTAMP}${TSTAMP}"/>

Modified: trunk/project.properties
Url: http://scarab.tigris.org/source/browse/scarab/trunk/project.properties?view=diff&rev=10486&p1=trunk/project.properties&p2=trunk/project.properties&r1=10485&r2=10486
==============================================================================
--- trunk/project.properties	(original)
+++ trunk/project.properties	2007-12-04 08:00:13-0800
@@ -876,6 +876,7 @@
 #   session.timeout
 #   services.UploadService.repository
 #   searchindex.path
+#   searchindex.analyuerClass
 # 
 #  Turbine related properties
 # 
@@ -886,6 +887,23 @@
 services.UploadService.repository=WEB-INF
 searchindex.path=WEB-INF/index
 
+# -------------------------
+# searchindex.analyzerClass
+# -------------------------
+#
+# 
+#  Analyzer class which Lucene uses to index text entered into Scarab.
+#  
+#  The default Analyzer is optimized for indexing English text.
+#  If your Scarab contains mostly non-English text you may want to
+#  switch to an Analyzer optimized for your language.
+#  Eg. for German you could use: org.apache.lucene.analysis.de.GermanAnalyzer
+#  The package org.apache.lucene.analysis contains Analyzers for a lot of
+#  other Languages.
+#  Of course you are free to write your own Analyzer. 
+
+searchindex.analyzerClass=org.tigris.scarab.util.word.PorterStemAnalyzer
+
 # ===============================
 # End of Group Turbine-properties
 # ===============================

Modified: trunk/project.xml
Url: http://scarab.tigris.org/source/browse/scarab/trunk/project.xml?view=diff&rev=10486&p1=trunk/project.xml&p2=trunk/project.xml&r1=10485&r2=10486
==============================================================================
--- trunk/project.xml	(original)
+++ trunk/project.xml	2007-12-04 08:00:13-0800
@@ -431,12 +431,23 @@
     </dependency>
     <dependency>
       <groupId>lucene</groupId>
-      <artifactId>lucene</artifactId>
-      <version>1.2</version>
+      <artifactId>lucene-core</artifactId>
+      <version>2.2.0</version>
       <type>jar</type>
       <properties>
         <war.bundle>true</war.bundle>
       </properties>
+      <url>http://lucene.apache.org/java/docs/index.html</url>
+    </dependency>
+    <dependency>
+      <groupId>lucene</groupId>
+      <artifactId>lucene-analyzers</artifactId>
+      <version>2.2.0</version>
+      <type>jar</type>
+      <properties>
+        <war.bundle>true</war.bundle>
+      </properties>
+      <url>http://lucene.apache.org/java/docs/index.html</url>
     </dependency>
     <dependency>
       <groupId>javamail</groupId>

Modified: trunk/src/conf/classes/ScarabBundle_de.properties
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/conf/classes/ScarabBundle_de.properties?view=diff&rev=10486&p1=trunk/src/conf/classes/ScarabBundle_de.properties&p2=trunk/src/conf/classes/ScarabBundle_de.properties&r1=10485&r2=10486
==============================================================================
--- trunk/src/conf/classes/ScarabBundle_de.properties	(original)
+++ trunk/src/conf/classes/ScarabBundle_de.properties	2007-12-04 08:00:13-0800
@@ -861,7 +861,7 @@
 GlobalIssueTypes=Globale Ticket-Typen
 GlobalAttributes=Globale Attribute
 UpdateSearchIndex=Such-Index aktualisieren
-UpdateSearchIndexBody=Klicken Sie auf die "Suchindex aktualisieren" Schaltfläche um den Lucene Suchindex wiederherzustellen falls er beschädigt wurde oder verloren ging. Wenn Sie die Schaltläche unten betätigen, wird die Seite solange aktualisiert, bis der Index wieder hergestellt ist. Das kann ein sehr Ressourcen intensiver Prozess sein, führen Sie deshalb diese Aktion mit Vorsicht aus und unterbrechen Sie den Vorgang nicht.
+UpdateSearchIndexBody=Klicken Sie auf die "Suchindex aktualisieren" Schaltfläche um den Lucene Suchindex wiederherzustellen falls er beschädigt wurde oder verloren ging. Wenn Sie die Schaltläche unten betätigen, wird die Seite solange aktualisiert, bis der Index wieder hergestellt ist. Das kann ein sehr Ressourcen intensiver Prozess sein.
 Approve=Anträge prüfen
 Modules=Module
 AdminManageIssueTypes=Ticket-Typen verwalten
@@ -1148,7 +1148,8 @@
 ## ***********************************************************************
 
 SearchIndexUpdated=Such-Index wurde aktualisiert.
-SearchIndexDoNoteLeavePage=Suchindex wird gerade aktualisiert. Bitte verlassen Sie diese Seite nicht, sie wird in {0} Sekunden aktualisiert.
+SearchIndexRebuildInProgress=Suchindex wird gerade aktualisiert. Aktualisierung zu {0}% abgeschlossen.
+SearchIndexRebuildCancelled=Aktualisierung von Suchindex abgebrochen.
 
 ## used in several actions
 SelectAttribute=Bitte wählen Sie ein Attribut.

Modified: trunk/src/conf/classes/ScarabBundle_en.properties
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/conf/classes/ScarabBundle_en.properties?view=diff&rev=10486&p1=trunk/src/conf/classes/ScarabBundle_en.properties&p2=trunk/src/conf/classes/ScarabBundle_en.properties&r1=10485&r2=10486
==============================================================================
--- trunk/src/conf/classes/ScarabBundle_en.properties	(original)
+++ trunk/src/conf/classes/ScarabBundle_en.properties	2007-12-04 08:00:13-0800
@@ -925,7 +925,7 @@
 GlobalIssueTypes=Global issue types
 GlobalAttributes=Global attributes
 UpdateSearchIndex=Update search index
-UpdateSearchIndexBody=Click the "Update search index" button below to re-create the Lucene search indexes in case they have been corrupted or lost. When you click the button below, the page will continue to refresh until the index is done updating. This can be a very resource intensive process, so please perform this action with caution and please do not stop this process until it is complete.
+UpdateSearchIndexBody=Click the "Update search index" button below to re-create the Lucene search indexes in case they have been corrupted or lost. When you click the button below, the page will continue to refresh until the index is done updating. This can be a very resource intensive process.
 Approve=Approve
 Modules=Modules
 CurrentModule=Current module
@@ -1221,7 +1221,8 @@
 ## ***********************************************************************
 
 SearchIndexUpdated=Search index has been updated.
-SearchIndexDoNoteLeavePage=Search index is currently being updated. Please do not leave this page, it will refresh in {0} seconds.
+SearchIndexRebuildInProgress=Search index is currently being updated. Update {0}% completed.
+SearchIndexRebuildCancelled=Update of search index cancelled.
 
 ## used in several actions
 SelectAttribute=Please select an attribute.

Modified: trunk/src/conf/classes/ScarabBundle_es.properties
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/conf/classes/ScarabBundle_es.properties?view=diff&rev=10486&p1=trunk/src/conf/classes/ScarabBundle_es.properties&p2=trunk/src/conf/classes/ScarabBundle_es.properties&r1=10485&r2=10486
==============================================================================
--- trunk/src/conf/classes/ScarabBundle_es.properties	(original)
+++ trunk/src/conf/classes/ScarabBundle_es.properties	2007-12-04 08:00:13-0800
@@ -896,7 +896,7 @@
 GlobalIssueTypes = Tipos de petición globales
 GlobalAttributes = Atributos globales
 UpdateSearchIndex = Actualizar índice de búsqueda
-UpdateSearchIndexBody = Pulsa en "Actualizar índice de búsqueda" para recrear los índices de búsqueda de Lucene, en caso de que se hayan corrompido o perdido. Cuando pulses, la página continuará refrescándose hasta que el índice se haya actualizado. Este proceso requiere muchos recursos, así que debe realizarse con precacución, y no debe denerse hasta que se complete.
+UpdateSearchIndexBody = Pulsa en "Actualizar índice de búsqueda" para recrear los índices de búsqueda de Lucene, en caso de que se hayan corrompido o perdido. Cuando pulses, la página continuará refrescándose hasta que el índice se haya actualizado. Este proceso requiere muchos recursos.
 Approve = Aprobaciones
 Modules = Módulos
 CurrentModule = Módulo actual
@@ -1189,7 +1189,6 @@
 ## ***********************************************************************
 
 SearchIndexUpdated = El índice de búsqueda ha sido actualizado.
-SearchIndexDoNoteLeavePage = El índice de búsqueda está siendo actualizado. Por favor, no dejes esta página. Se refrescará en {0} segundos.
 
 ## used in several actions
 SelectAttribute = Selecciona un atributo.

Modified: trunk/src/conf/classes/ScarabBundle_fr.properties
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/conf/classes/ScarabBundle_fr.properties?view=diff&rev=10486&p1=trunk/src/conf/classes/ScarabBundle_fr.properties&p2=trunk/src/conf/classes/ScarabBundle_fr.properties&r1=10485&r2=10486
==============================================================================
--- trunk/src/conf/classes/ScarabBundle_fr.properties	(original)
+++ trunk/src/conf/classes/ScarabBundle_fr.properties	2007-12-04 08:00:13-0800
@@ -919,7 +919,7 @@
 GlobalIssueTypes = Types de fiches globaux
 GlobalAttributes = Attributs globaux
 UpdateSearchIndex = Mise à jour des index de recherche (gourmand en ressources)
-UpdateSearchIndexBody = Cliquez le bouton "Mise à jour des index de recherche" ci-dessous pour recréer les index de recherche de Lucene au cas où ils auraient été corrompus ou perdus. Cette opération peut requérir beaucoup de ressources, il ne faut donc la lancer qu'avec précaution.
+UpdateSearchIndexBody = Cliquez le bouton "Mise à jour des index de recherche" ci-dessous pour recréer les index de recherche de Lucene au cas où ils auraient été corrompus ou perdus. Cette opération peut requérir beaucoup de ressources.
 Approve = Approbations
 Modules = Modules
 AdminManageIssueTypes = Gérer les types de fiches
@@ -1213,7 +1213,6 @@
 ## ***********************************************************************
 
 SearchIndexUpdated = L'index de recherche a été mis à jour.
-SearchIndexDoNoteLeavePage = L''index de recherche est en cours de mise à jour. Ne quittez pas cette page, elle sera rafraîchie dans {0} secondes.
 
 ## used in several actions
 SelectAttribute = Veuillez sélectionner un attribut.
@@ -2267,4 +2266,4 @@
 ActivityDependencies = Modifications de dépendances
 
 ReasonSavedAs = Enregistrer la raison comme
-EnterReasonAs = pour l'ajouter à cette fiche lorsque vous cliquez le bouton Terminer
\ No newline at end of file
+EnterReasonAs = pour l'ajouter à cette fiche lorsque vous cliquez le bouton Terminer

Modified: trunk/src/conf/classes/ScarabBundle_it.properties
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/conf/classes/ScarabBundle_it.properties?view=diff&rev=10486&p1=trunk/src/conf/classes/ScarabBundle_it.properties&p2=trunk/src/conf/classes/ScarabBundle_it.properties&r1=10485&r2=10486
==============================================================================
--- trunk/src/conf/classes/ScarabBundle_it.properties	(original)
+++ trunk/src/conf/classes/ScarabBundle_it.properties	2007-12-04 08:00:13-0800
@@ -857,7 +857,7 @@
 GlobalIssueTypes=Tipologie di segnalazione globali
 GlobalAttributes=Attributi globali (di sistema)
 UpdateSearchIndex=Aggiorna indice di ricerca
-UpdateSearchIndexBody=Clicca il bottone "Aggiorna indice di ricarca" per ricreare l'indicie di ricerca in caso sia stato corrotto o sia andato perso. Una volta cliccato il bootne questa pagina continuerà ad aggiornarsi finchè l'indice non sarà aggiornato. Questo può essere un processo abbastanza pesante, pertanto poni attenzione a quando eseguirlo e non interromperlo finchè non è completato.
+UpdateSearchIndexBody=Clicca il bottone "Aggiorna indice di ricarca" per ricreare l'indicie di ricerca in caso sia stato corrotto o sia andato perso. Una volta cliccato il bootne questa pagina continuerà ad aggiornarsi finchè l'indice non sarà aggiornato. Questo può essere un processo abbastanza pesante.
 Approve=Approva
 Modules=Moduli
 AdminManageIssueTypes=Gestisci tipologie segnalazione
@@ -1145,7 +1145,6 @@
 ## ***********************************************************************
 
 SearchIndexUpdated=L'indice di ricerca è stato aggiornato.
-SearchIndexDoNoteLeavePage=Aggiornamento in corso dell''indice di ricerca. Non cambiare pagine per favore, si auto aggiornerà in {0} secondi.
 
 ## used in several actions
 SelectAttribute=Selezionare un attributo.
@@ -2148,4 +2147,4 @@
 DateFirstWeekDay = 0
 DateWeekDays = "Dom", "Lun", "Mar", "Mer", "Gio", "Ven", "Sab"
 DateToday=Oggi
-DateClean=Cancella
\ No newline at end of file
+DateClean=Cancella

Modified: trunk/src/conf/classes/ScarabBundle_ja.properties
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/conf/classes/ScarabBundle_ja.properties?view=diff&rev=10486&p1=trunk/src/conf/classes/ScarabBundle_ja.properties&p2=trunk/src/conf/classes/ScarabBundle_ja.properties&r1=10485&r2=10486
==============================================================================
--- trunk/src/conf/classes/ScarabBundle_ja.properties	(original)
+++ trunk/src/conf/classes/ScarabBundle_ja.properties	2007-12-04 08:00:13-0800
@@ -787,7 +787,6 @@
 GlobalIssueTypes=\u5171\u901a\u6848\u4ef6\u7a2e\u5225
 GlobalAttributes=\u5171\u901a\u5c5e\u6027
 UpdateSearchIndex=\u691c\u7d22\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u306e\u66f4\u65b0
-UpdateSearchIndexBody=Lucene \u306e\u691c\u7d22\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u304c\u58ca\u308c\u305f\u308a\u5931\u308f\u308c\u3066\u3057\u307e\u3063\u305f\u5834\u5408\u306b\u3053\u308c\u3092\u518d\u69cb\u7bc9\u3059\u308b\u306b\u306f\u4e0b\u306e"\u691c\u7d22\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u306e\u66f4\u65b0"\u30dc\u30bf\u30f3\u3092\u30af\u30ea\u30c3\u30af\u3057\u3066\u4e0b\u3055\u3044\u3002\u30dc\u30bf\u30f3\u3092\u30af\u30ea\u30c3\u30af\u3059\u308b\u3068\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u304c\u66f4\u65b0\u3055\u308c\u308b\u307e\u3067\u306f\u30da\u30fc\u30b8\u304c\u66f4\u65b0\u3055\u308c\u3064\u3065\u3051\u307e\u3059\u3002\u3053\u306e\u51e6\u7406\u306f\u975e\u5e38\u306b\u30ea\u30bd\u30fc\u30b9\u3092\u6d88\u8cbb\u3059\u308b\u51e6\u7406\u3067\u3042\u308b\u305f\u3081\u3001\u6ce8
 \u610f\u3057\u3066\u5b9f\u884c\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u307e\u305f\u51e6\u7406\u304c\u5b8c\u4e86\u3059\u308b\u307e\u3067\u4e2d\u65ad\u3057\u306a\u3044\u3067\u304f\u3060\u3055\u3044\u3002
 Approve=\u8a8d\u53ef
 Modules=\u30e2\u30b8\u30e5\u30fc\u30eb
 AdminManageIssueTypes=\u6848\u4ef6\u7a2e\u5225\u306e\u7ba1\u7406
@@ -1073,7 +1072,6 @@
 ## ***********************************************************************
 
 SearchIndexUpdated=\u691c\u7d22\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u306f\u66f4\u65b0\u3055\u308c\u307e\u3057\u305f\u3002
-SearchIndexDoNoteLeavePage=\u691c\u7d22\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u306f\u73fe\u5728\u66f4\u65b0\u4e2d\u3067\u3059\u3002\u3053\u306e\u30da\u30fc\u30b8\u3092\u9589\u3058\u306a\u3044\u3067\u304f\u3060\u3055\u3044\u3001{0} \u79d2\u5f8c\u306b\u3053\u306e\u753b\u9762\u306f\u518d\u8868\u793a\u3055\u308c\u307e\u3059\u3002
 
 ## used in several actions
 SelectAttribute=\u5c5e\u6027\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002

Modified: trunk/src/conf/classes/ScarabBundle_ko.properties
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/conf/classes/ScarabBundle_ko.properties?view=diff&rev=10486&p1=trunk/src/conf/classes/ScarabBundle_ko.properties&p2=trunk/src/conf/classes/ScarabBundle_ko.properties&r1=10485&r2=10486
==============================================================================
--- trunk/src/conf/classes/ScarabBundle_ko.properties	(original)
+++ trunk/src/conf/classes/ScarabBundle_ko.properties	2007-12-04 08:00:13-0800
@@ -798,7 +798,7 @@
 GlobalIssueTypes = \uc774 \ud654\uba74\uc740 \uae00\ub85c\ubc8c \uc2a4\ucf54\ud504\uc5d0 \uc815\uc758\ub418\uc5b4 \uc788\ub294 \uac83\uc744 \ud3b8\uc9d1\ud558\uae30 \uc704\ud558\uc5ec \uc774\uc288 \ud0c0\uc785\uc744 \uc120\ud0dd\ud558\uae30 \uc704\ud55c \uac83 \uc785\ub2c8\ub2e4.
 GlobalAttributes = [ko] On this screen, one can modify system wide Attribute information.
 UpdateSearchIndex = Update search index (resource intensive)
-UpdateSearchIndexBody = Click the "Update search index" button below to re-create the Lucene search indexes in case they have been corrupted or lost. When you click the button below, the page will continue to refresh until the index is done updating. This can be a very resource intensive process, so please perform this action with caution and please do not stop this process until it is complete.
+UpdateSearchIndexBody=Click the "Update search index" button below to re-create the Lucene search indexes in case they have been corrupted or lost. When you click the button below, the page will continue to refresh until the index is done updating. This can be a very resource intensive process.
 Approve = \uc2b9\uc778\uad00\ub9ac
 Modules = \ubaa8\ub4c8 \ud648
 AdminManageIssueTypes = [ko]Manage issue types
@@ -1084,7 +1084,6 @@
 ## ***********************************************************************
 
 SearchIndexUpdated = \uc11c\uce58 \uc778\ub371\uc2a4\uac00 \ubcc0\uacbd\ub418\uc5c8\uc2b5\ub2c8\ub2e4.
-SearchIndexDoNoteLeavePage = \uc9c0\uae08 \uc11c\uce58 \uc778\ub371\uc2a4\ub97c \ubcc0\uacbd\ud558\uace0 \uc788\ub294 \uc911\uc785\ub2c8\ub2e4. \uc774 \ud654\uba74\uc744 \uae30\ub2e4\ub824 \uc8fc\uc2dc\uae30 \ubc14\ub78d\ub2c8\ub2e4. {0} \ucd08 \ud6c4\uc5d0 \ub2e4\uc2dc \ud654\uba74\uc774 \uac31\uc2e0\ub429\ub2c8\ub2e4. 
 
 ## used in several actions
 SelectAttribute = Please select an attribute.

Modified: trunk/src/conf/classes/ScarabBundle_nl.properties
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/conf/classes/ScarabBundle_nl.properties?view=diff&rev=10486&p1=trunk/src/conf/classes/ScarabBundle_nl.properties&p2=trunk/src/conf/classes/ScarabBundle_nl.properties&r1=10485&r2=10486
==============================================================================
--- trunk/src/conf/classes/ScarabBundle_nl.properties	(original)
+++ trunk/src/conf/classes/ScarabBundle_nl.properties	2007-12-04 08:00:13-0800
@@ -766,7 +766,7 @@
 GlobalIssueTypes = Globale kaartsoorten
 GlobalAttributes = Globale attributen
 UpdateSearchIndex = Bijwerken zoek index
-UpdateSearchIndexBody = klik de "Bijwerken zoek index" knop om de Lucene zoek indexen opnieuw aan te maken in geval deze corrupt of verloren gegaan zijn. Wanneer u de onderstaande knop aanklikt, zal de pagina continue vernieuwd worden totdat de index bijgewerkt is. Dit kan erg belastend zijn voor het systeem, dus gebruik deze functie alleen als het nodig is en onderbreek dit proces niet voordat het klaar is.
+UpdateSearchIndexBody = klik de "Bijwerken zoek index" knop om de Lucene zoek indexen opnieuw aan te maken in geval deze corrupt of verloren gegaan zijn. Wanneer u de onderstaande knop aanklikt, zal de pagina continue vernieuwd worden totdat de index bijgewerkt is. Dit kan erg belastend zijn voor het systeem.
 Approve = Goedkeuren
 Modules = Modules
 AdminManageIssueTypes = Beheer kaartsoorten
@@ -1042,7 +1042,6 @@
 ## ***********************************************************************
 
 SearchIndexUpdated = Zoek index is bijgewerkt.
-SearchIndexDoNoteLeavePage = Zoek index wordt nu bijgewerkt. Verlaat deze pagina niet, het ververst zichzelf in {0} seconden.
 
 ## used in several actions
 SelectAttribute = Selecteer een attribuut.

Modified: trunk/src/conf/classes/ScarabBundle_pl.properties
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/conf/classes/ScarabBundle_pl.properties?view=diff&rev=10486&p1=trunk/src/conf/classes/ScarabBundle_pl.properties&p2=trunk/src/conf/classes/ScarabBundle_pl.properties&r1=10485&r2=10486
==============================================================================
--- trunk/src/conf/classes/ScarabBundle_pl.properties	(original)
+++ trunk/src/conf/classes/ScarabBundle_pl.properties	2007-12-04 08:00:13-0800
@@ -928,7 +928,7 @@
 GlobalIssueTypes=Globalne typy zagadnie\u0144
 GlobalAttributes=Globalne atrybuty
 UpdateSearchIndex=Uaktualnij indeks wyszukiwania
-UpdateSearchIndexBody=Kliknij na "Uaktualnij indeks wyszukiwania" poni\u017cej, aby utworzy\u0107 ponownie indeks wyszukiwania Lucene w przypadku gdy zosta\u0142 uszkodzony lub utracony. Gdy klikniesz na przycisk poni\u017cej, strona b\u0119dzie od\u015bwie\u017cana do czasu aktualizacji indeksu. To mo\u017ce by\u0107 bardzo "kosztowny" proces, wi\u0119c prosz\u0119 o ostro\u017cno\u015b\u0107 oraz nie przerywanie tej operacji do momentu jej zako\u0144czenia.
+UpdateSearchIndexBody=Kliknij na "Uaktualnij indeks wyszukiwania" poni\u017cej, aby utworzy\u0107 ponownie indeks wyszukiwania Lucene w przypadku gdy zosta\u0142 uszkodzony lub utracony. Gdy klikniesz na przycisk poni\u017cej, strona b\u0119dzie od\u015bwie\u017cana do czasu aktualizacji indeksu. To mo\u017ce by\u0107 bardzo "kosztowny" proces.
 Approve=Zatwierd\u017a
 Modules=Modu\u0142y
 AdminManageIssueTypes=Zarz\u0105dzanie typami zagadnie\u0144
@@ -1222,7 +1222,6 @@
 ## ***********************************************************************
 
 SearchIndexUpdated=Indeks wyszukiwania zosta\u0142 zaktualizowany.
-SearchIndexDoNoteLeavePage=Indeks wyszukiwania jest teraz aktualizowany. Prosz\u0119 nie opuszcza\u0107 tej strony, od\u015bwie\u017cy si\u0119 za {0} sekundy.
 
 ## used in several actions
 SelectAttribute=Prosz\u0119 wybra\u0107 atrybut.

Modified: trunk/src/conf/classes/ScarabBundle_pt_BR.properties
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/conf/classes/ScarabBundle_pt_BR.properties?view=diff&rev=10486&p1=trunk/src/conf/classes/ScarabBundle_pt_BR.properties&p2=trunk/src/conf/classes/ScarabBundle_pt_BR.properties&r1=10485&r2=10486
==============================================================================
--- trunk/src/conf/classes/ScarabBundle_pt_BR.properties	(original)
+++ trunk/src/conf/classes/ScarabBundle_pt_BR.properties	2007-12-04 08:00:13-0800
@@ -775,7 +775,7 @@
 GlobalIssueTypes=Tipos de item Globais
 GlobalAttributes=Atributos globais
 UpdateSearchIndex=Atualizar índice de busca
-UpdateSearchIndexBody=Cliqe no botão 'Atualizar índice de busca' abaixo para recriar os índices de busca no caso deles terem sido corrompidos ou perdidos. Quando você clica no botão abaixo, a página continuará a atualizar até que os índices forem atualizados. Isto pode ser um processo que consuma muitos recursos, então utilize esta opção com cuidado e não pare este processo até que esteja finalizado.
+UpdateSearchIndexBody=Cliqe no botão 'Atualizar índice de busca' abaixo para recriar os índices de busca no caso deles terem sido corrompidos ou perdidos. Quando você clica no botão abaixo, a página continuará a atualizar até que os índices forem atualizados. Isto pode ser um processo que consuma muitos recursos.
 Approve=Aprovar
 Modules=Módulos
 AdminManageIssueTypes=Gerenciar tipos de item
@@ -1053,7 +1053,6 @@
 ## ***********************************************************************
 
 SearchIndexUpdated=O índice de busca foi atualizado.
-SearchIndexDoNoteLeavePage=O índice de busca está sendo atualizado agora. Por favor não deixe esta página pois ela irá ser atualizada em {0} segundos.
 
 ## used in several actions
 SelectAttribute=Por favor selecione um atributo.

Modified: trunk/src/conf/classes/ScarabBundle_ru.properties
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/conf/classes/ScarabBundle_ru.properties?view=diff&rev=10486&p1=trunk/src/conf/classes/ScarabBundle_ru.properties&p2=trunk/src/conf/classes/ScarabBundle_ru.properties&r1=10485&r2=10486
==============================================================================
--- trunk/src/conf/classes/ScarabBundle_ru.properties	(original)
+++ trunk/src/conf/classes/ScarabBundle_ru.properties	2007-12-04 08:00:13-0800
@@ -2946,7 +2946,6 @@
 
 SearchIn = \u0418\u0441\u043A\u0430\u0442\u044C \u0432
 
-SearchIndexDoNoteLeavePage = Search index is currently being upated. Please do not leave this page, it will refresh in {0} seconds.
 
 ## ***********************************************************************
 ## Actions
@@ -3486,7 +3485,7 @@
 
 UpdateSearchIndex = Update search index (resource intensive)
 
-UpdateSearchIndexBody = Click the "Update search index" button below to re-create the Lucene search indexes in case they have been corrupted or lost. When you click the button below, the page will continue to refresh until the index is done updating. This can be a very resource intensive process, so please perform this action with caution and please do not stop this process until it is complete.
+UpdateSearchIndexBody=Click the "Update search index" button below to re-create the Lucene search indexes in case they have been corrupted or lost. When you click the button below, the page will continue to refresh until the index is done updating. This can be a very resource intensive process.
 
 UpdateSelected = \u0418\u0437\u043C\u0435\u043D\u0438\u0442\u044C \u0432\u044B\u0431\u0440\u0430\u043D\u043D\u043E\u0435
 

Modified: trunk/src/conf/classes/ScarabBundle_zh_CN.properties
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/conf/classes/ScarabBundle_zh_CN.properties?view=diff&rev=10486&p1=trunk/src/conf/classes/ScarabBundle_zh_CN.properties&p2=trunk/src/conf/classes/ScarabBundle_zh_CN.properties&r1=10485&r2=10486
==============================================================================
--- trunk/src/conf/classes/ScarabBundle_zh_CN.properties	(original)
+++ trunk/src/conf/classes/ScarabBundle_zh_CN.properties	2007-12-04 08:00:13-0800
@@ -798,7 +798,6 @@
 GlobalIssueTypes = \u5168\u5c40\u6848\u4ef6\u5206\u7c7b
 GlobalAttributes = \u5168\u5c40\u5c5e\u6027
 UpdateSearchIndex = \u4fee\u6539\u641c\u7d22\u7d22\u5f15
-UpdateSearchIndexBody = \u70b9\u51fb"\u4fee\u6539\u641c\u7d22\u7d22\u5f15"\u6309\u94ae\u91cd\u65b0\u751f\u6210 Lucene \u67e5\u8be2\u7d22\u5f15\uff08\u4ec5\u5f53\u4ed6\u4eec\u635f\u574f\u6216\u4e22\u5931\uff0cLucene\u662f Jakarta \u6b63\u6587\u641c\u7d22\u5de5\u5177\u5305\uff09\u3002\u5f53\u4f60\u70b9\u51fb\u4e0b\u9762\u7684\u6309\u94ae, \u5728\u7d22\u5f15\u91cd\u5efa\u6ca1\u6709\u5b8c\u6210\u524d\u9875\u9762\u5c06\u4e0d\u505c\u7684\u5237\u65b0\u3002\u8fd9\u9879\u64cd\u4f5c\u5c06\u975e\u5e38\u6d88\u7cfb\u7edf\u8d44\u6e90\uff0c\u5e76\u4e14\u5728\u64cd\u4f5c\u65f6\u8981\u975e\u5e38\u5c0f\u5fc3\uff0c\u5728\u64cd\u4f5c\u6ca1\u6709\u505c\u6b62\u524d\u4e0d\u8981\u4eba\u5de5\u4e2d\u65ad\u3002
 Approve = \u6838\u51c6
 Modules = \u6a21\u5757
 AdminManageIssueTypes = \u6848\u4ef6\u5206\u7c7b\u7ba1\u7406
@@ -1092,7 +1091,6 @@
 ## ***********************************************************************
 
 SearchIndexUpdated = \u6b63\u6587\u67e5\u8be2\u7d22\u5f15\u5df2\u88ab\u66f4\u65b0\u3002
-SearchIndexDoNoteLeavePage = \u6b63\u6587\u67e5\u8be2\u7d22\u5f15\u6b63\u5728\u66f4\u65b0\u4e2d\u3002\u8bf7\u4e0d\u8981\u79bb\u5f00\u6b64\u9875\u9762\uff0c\u9875\u9762\u5c06\u5728 {0} \u79d2\u4e2d\u5237\u65b0\u3002
 
 
 ## used in several actions

Modified: trunk/src/conf/classes/ScarabBundle_zh_TW.properties
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/conf/classes/ScarabBundle_zh_TW.properties?view=diff&rev=10486&p1=trunk/src/conf/classes/ScarabBundle_zh_TW.properties&p2=trunk/src/conf/classes/ScarabBundle_zh_TW.properties&r1=10485&r2=10486
==============================================================================
--- trunk/src/conf/classes/ScarabBundle_zh_TW.properties	(original)
+++ trunk/src/conf/classes/ScarabBundle_zh_TW.properties	2007-12-04 08:00:13-0800
@@ -852,7 +852,6 @@
 GlobalIssueTypes=Global issue types
 GlobalAttributes=Global attributes
 UpdateSearchIndex=Update search index
-UpdateSearchIndexBody=Click the "Update search index" button below to re-create the Lucene search indexes in case they have been corrupted or lost. When you click the button below, the page will continue to refresh until the index is done updating. This can be a very resource intensive process, so please perform this action with caution and please do not stop this process until it is complete.
 Approve=\u6838\u53ef
 Modules=\u6a21\u7d44
 AdminManageIssueTypes=\u8b70\u984c\u7a2e\u985e\u7ba1\u7406
@@ -1140,7 +1139,6 @@
 ## ***********************************************************************
 
 SearchIndexUpdated=Search index has been updated.
-SearchIndexDoNoteLeavePage=Search index is currently being updated. Please do not leave this page, it will refresh in {0} seconds.
 
 ## used in several actions
 SelectAttribute=Please select an attribute.

Modified: trunk/src/conf/conf/componentConfiguration.xml
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/conf/conf/componentConfiguration.xml?view=diff&rev=10486&p1=trunk/src/conf/conf/componentConfiguration.xml&p2=trunk/src/conf/conf/componentConfiguration.xml&r1=10485&r2=10486
==============================================================================
--- trunk/src/conf/conf/componentConfiguration.xml	(original)
+++ trunk/src/conf/conf/componentConfiguration.xml	2007-12-04 08:00:13-0800
@@ -29,7 +29,6 @@
         # Path for writing index, if starts with a '/', the path is assumed to be 
         # absolute, otherwise it will be created relative to the webapp root.
     -->
-    <searchIndex path="@SEARCH_INDEX_PATH@" />
     <XmlRpcComponent>
         <!-- Port on which the XML-RPC server will listen for
             incoming connections -->

Modified: trunk/src/conf/conf/componentRoles.xml
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/conf/conf/componentRoles.xml?view=diff&rev=10486&p1=trunk/src/conf/conf/componentRoles.xml&p2=trunk/src/conf/conf/componentRoles.xml&r1=10485&r2=10486
==============================================================================
--- trunk/src/conf/conf/componentRoles.xml	(original)
+++ trunk/src/conf/conf/componentRoles.xml	2007-12-04 08:00:13-0800
@@ -66,7 +66,7 @@
         shorthand="quartz"
         default-class="org.apache.fulcrum.quartz.impl.DefaultQuartzScheduler"/>        
     <role
-        name="org.tigris.scarab.util.word.SearchIndex"
+        name="org.tigris.scarab.util.word.LuceneSearchIndex"
         shorthand="searchIndex"
         default-class="org.tigris.scarab.util.word.LuceneSearchIndex"/>
     <role

Modified: trunk/src/java/org/tigris/scarab/actions/admin/UpdateSearchIndex.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/actions/admin/UpdateSearchIndex.java?view=diff&rev=10486&p1=trunk/src/java/org/tigris/scarab/actions/admin/UpdateSearchIndex.java&p2=trunk/src/java/org/tigris/scarab/actions/admin/UpdateSearchIndex.java&r1=10485&r2=10486
==============================================================================
--- trunk/src/java/org/tigris/scarab/actions/admin/UpdateSearchIndex.java	(original)
+++ trunk/src/java/org/tigris/scarab/actions/admin/UpdateSearchIndex.java	2007-12-04 08:00:13-0800
@@ -53,11 +53,11 @@
 
 // Scarab Stuff
 import org.tigris.scarab.tools.ScarabRequestTool;
-import org.tigris.scarab.tools.ScarabLocalizationTool;
+import org.tigris.scarab.tools.localization.L10NKeySet;
+import org.tigris.scarab.tools.localization.L10NMessage;
 import org.tigris.scarab.actions.base.RequireLoginFirstAction;
 import org.tigris.scarab.util.word.SearchFactory;
-import org.tigris.scarab.util.word.SearchIndex;
-import org.tigris.scarab.util.Log;
+import org.tigris.scarab.util.word.LuceneSearchIndex;
 
 /**
  * This class allows an admin to update the search index. It performs
@@ -71,64 +71,33 @@
  */
 public class UpdateSearchIndex extends RequireLoginFirstAction
 {
-    private static ThreadGroup tg = null;
-    private static int seconds = 5;
-    private static int counter = 0;
 
-    private void reset()
-    {
-        seconds = 5;
-        counter = 0;
-        tg = null;
-    }    
+    //TODO static should work, because there is only one SearchIndex, but its not a clean solution
+    private static boolean isRunning;
 
     public void doPerform(RunData data, TemplateContext context)
         throws Exception
     {
         ScarabRequestTool scarabR = getScarabRequestTool(context);
-        ScarabLocalizationTool l10n = getLocalizationTool(context);
+        LuceneSearchIndex index = SearchFactory.getInstance();
         
-        synchronized (this)
+        if(isRunning)
+        {
+            isRunning = index.isRebuildInProgress();
+            
+            if(!isRunning)
+                scarabR.setConfirmMessage( new L10NMessage( L10NKeySet.SearchIndexUpdated ));               
+        }
+        else
         {
-            Integer inttime = new Integer(seconds);
-            Object[] time = {inttime};
-            if (tg == null)
-            {
-                try
-                {
-                    tg = new ThreadGroup("UpdateIndex");
-                    Thread updateThread = new Thread(tg, new UpdateThread());
-                    updateThread.start();
-                    context.put("updateFrequency", inttime.toString());
-                    scarabR.setConfirmMessage(l10n.format("SearchIndexDoNoteLeavePage",time));
-                }
-                catch (Exception e)
-                {
-                    reset();
-                    context.put("updateFrequency", "");
-                    scarabR.setAlertMessage(l10n.getMessage(e));            
-                }
-            }
-            else if (tg.activeCount() == 0)
-            {
-                reset();
-                context.put("updateFrequency", "");
-                scarabR.setConfirmMessage(l10n.get("SearchIndexUpdated"));
-            }
-            else
-            {
-                if (counter > 5)
-                {
-                    seconds = 15;
-                }
-                else if (counter > 10)
-                {
-                    seconds = 20;
-                }
-                context.put("updateFrequency", inttime.toString());
-                scarabR.setConfirmMessage(l10n.format("SearchIndexDoNoteLeavePage",time));
-                counter++;
-            }
+            index.startRebuild();
+            isRunning=true;
+        }            
+
+        if(isRunning){
+            scarabR.setConfirmMessage( new L10NMessage( L10NKeySet.SearchIndexRebuildInProgress, index.pctRebuildFinished()));
+            context.put("updateFrequency", "10" );
+            context.put("rebuildInProgress", Boolean.TRUE);
         }
 
         String template = getCurrentTemplate(data, null);
@@ -136,25 +105,19 @@
         setTarget(data, nextTemplate);
     }
 
-    public class UpdateThread implements Runnable
+    public void doCancel(RunData data, TemplateContext context)
+        throws Exception
     {
-        public UpdateThread()
-        {
-        }
-
-        public void run()
-        {
-            try
-            {
-                Log.get().info("Update index started!");
-                SearchIndex indexer = SearchFactory.getInstance();
-                indexer.updateIndex();
-                Log.get().info("Update index completed!");
-            }
-            catch (Exception e)
-            {
-                Log.get().error("Update index failed:", e);
-            }
-        }
+        ScarabRequestTool scarabR = getScarabRequestTool(context);
+        LuceneSearchIndex index = SearchFactory.getInstance();
+        
+        index.cancelRebuild();
+        scarabR.setConfirmMessage( new L10NMessage( L10NKeySet.SearchIndexRebuildCancelled));
+    
+        String template = getCurrentTemplate(data, null);
+        String nextTemplate = getNextTemplate(data, template);
+        setTarget(data, nextTemplate);
     }
+    
+
 }

Modified: trunk/src/java/org/tigris/scarab/attribute/StringAttribute.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/attribute/StringAttribute.java?view=diff&rev=10486&p1=trunk/src/java/org/tigris/scarab/attribute/StringAttribute.java&p2=trunk/src/java/org/tigris/scarab/attribute/StringAttribute.java&r1=10485&r2=10486
==============================================================================
--- trunk/src/java/org/tigris/scarab/attribute/StringAttribute.java	(original)
+++ trunk/src/java/org/tigris/scarab/attribute/StringAttribute.java	2007-12-04 08:00:13-0800
@@ -48,8 +48,6 @@
 
 import java.sql.Connection;
 import org.apache.torque.TorqueException;
-import org.tigris.scarab.util.word.SearchIndex;
-import org.tigris.scarab.util.word.SearchFactory;
 
 
 /**
@@ -60,26 +58,4 @@
  */
 public class StringAttribute extends FreeFormAttribute
 {
-    /**
-     * Saves the StringAttribute and related objects in persistent
-     * storage.  This method calls the parent save method and then
-     * indexes the text value for searching.
-     */
-    public void save(Connection dbCon)
-        throws TorqueException
-    {
-        try
-        {
-            super.save(dbCon);
-            SearchIndex searchIndex = SearchFactory.getInstance();
-            if (searchIndex != null) 
-            {
-                searchIndex.index(this);
-            }
-        }
-        catch (Exception e)
-        {
-            throw new TorqueException(e); //EXCEPTION
-        }
-    }
 }

Modified: trunk/src/java/org/tigris/scarab/om/Attachment.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/om/Attachment.java?view=diff&rev=10486&p1=trunk/src/java/org/tigris/scarab/om/Attachment.java&p2=trunk/src/java/org/tigris/scarab/om/Attachment.java&r1=10485&r2=10486
==============================================================================
--- trunk/src/java/org/tigris/scarab/om/Attachment.java	(original)
+++ trunk/src/java/org/tigris/scarab/om/Attachment.java	2007-12-04 08:00:13-0800
@@ -57,7 +57,6 @@
 import java.sql.Connection;
 import java.util.Date;
 import java.util.List;
-import org.apache.torque.Torque;
 
 import org.apache.torque.TorqueException;
 import org.apache.torque.om.Persistent;
@@ -72,8 +71,6 @@
 import org.tigris.scarab.util.Log;
 import org.tigris.scarab.util.ScarabConstants;
 import org.tigris.scarab.util.ScarabException;
-import org.tigris.scarab.util.word.SearchIndex;
-import org.tigris.scarab.util.word.SearchFactory;
 
 /** 
  * Attachments contain data associated with an issue.  It used to be that
@@ -268,25 +265,6 @@
         {
             throw new TorqueException(e); //EXCEPTION
         }
-        
-        /*
-         * index the text for searching.
-         */
-        if (AttachmentTypePeer.COMMENT_PK.equals(getTypeId())) 
-        {
-            try
-            {
-                SearchIndex searchIndex = SearchFactory.getInstance();
-                if (searchIndex != null) 
-                {
-                    searchIndex.index(this);
-                }
-            }
-            catch (Exception e)
-            {
-                throw new TorqueException(e); //EXCEPTION
-            }
-        }
     }       
     
     /**
@@ -448,7 +426,7 @@
     }
     
     public void copyFileFromTo(final String from, final String path)
-        throws TorqueException, FileNotFoundException, IOException
+        throws FileNotFoundException, IOException
     {
         BufferedInputStream in = null;
         BufferedOutputStream out = null;

Modified: trunk/src/java/org/tigris/scarab/om/Issue.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/om/Issue.java?view=diff&rev=10486&p1=trunk/src/java/org/tigris/scarab/om/Issue.java&p2=trunk/src/java/org/tigris/scarab/om/Issue.java&r1=10485&r2=10486
==============================================================================
--- trunk/src/java/org/tigris/scarab/om/Issue.java	(original)
+++ trunk/src/java/org/tigris/scarab/om/Issue.java	2007-12-04 08:00:13-0800
@@ -88,6 +88,7 @@
 import org.tigris.scarab.util.MutableBoolean;
 import org.tigris.scarab.util.ScarabConstants;
 import org.tigris.scarab.util.ScarabException;
+import org.tigris.scarab.util.word.SearchFactory;
 import org.tigris.scarab.workflow.WorkflowFactory;
 
 import com.workingdogs.village.Record;
@@ -600,6 +601,8 @@
         NotificationManagerFactory.getInstance().addActivityNotification(
                 ActivityType.COMMENT_ADDED, activitySet, this, user);            
 
+        index();
+
         return activitySet;
     }
 
@@ -2631,6 +2634,8 @@
                                 ActivityType.ISSUE_MOVED,
                                 getUniqueId(), newIssue.getUniqueId());
 
+        newIssue.index();
+        
         return newIssue;
     }
 
@@ -3519,6 +3524,9 @@
         // issue is saved. for some reason, things don't
         // show up properly right away.
         ScarabCache.clear();
+        
+        index();
+        
         return activitySet;
     }
 
@@ -3600,9 +3608,24 @@
              getMethodResult().remove(this, GET_MODULE_ATTRVALUES_MAP,
                                           Boolean.TRUE);
         }
+
+        index();
+
         return activitySet;
     }
 
+    private void index()
+    {
+        try
+        {
+            SearchFactory.getInstance().index(this);
+        }
+        catch (Exception e)
+        {
+            throw new RuntimeException(e);
+        }
+    }
+
     /**
      * Sets an ActivitySet as the lastActivitySet of an Issue.
      * Crates and saves a new ActivitySet, if required.
@@ -3776,6 +3799,8 @@
                     ActivityType.COMMENT_CHANGED, activitySet,
                     this, user);            
         }
+        index();
+
         return activitySet;
     }
 

Modified: trunk/src/java/org/tigris/scarab/tools/ScarabRequestTool.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/tools/ScarabRequestTool.java?view=diff&rev=10486&p1=trunk/src/java/org/tigris/scarab/tools/ScarabRequestTool.java&p2=trunk/src/java/org/tigris/scarab/tools/ScarabRequestTool.java&r1=10485&r2=10486
==============================================================================
--- trunk/src/java/org/tigris/scarab/tools/ScarabRequestTool.java	(original)
+++ trunk/src/java/org/tigris/scarab/tools/ScarabRequestTool.java	2007-12-04 08:00:13-0800
@@ -134,12 +134,10 @@
 import org.tigris.scarab.util.ScarabLink;
 import org.tigris.scarab.util.ScarabPaginatedList;
 import org.tigris.scarab.util.SimpleSkipFiltering;
-import org.tigris.scarab.util.SnippetRenderer;
 import org.tigris.scarab.util.word.IssueSearch;
 import org.tigris.scarab.util.word.IssueSearchFactory;
 import org.tigris.scarab.util.word.MaxConcurrentSearchException;
 import org.tigris.scarab.util.word.QueryResult;
-import org.tigris.scarab.util.word.SearchIndex;
 import org.tigris.scarab.workflow.TransitionNode;
 import org.tigris.scarab.workflow.Workflow;
 
@@ -1814,23 +1812,13 @@
         {
             setAlertMessage(L10NKeySet.ResourceLimitationsPreventedSearch);
         }
+        catch (ScarabException e)
+        {
+            setAlertMessage(e.getL10nMessage());
+        }
         catch (Exception e)
         {
-            String queryError = e.getMessage();
-            if (queryError.startsWith(SearchIndex.PARSE_ERROR)) 
-            {
-                Log.get().info(queryError);
-                setAlertMessage(new SimpleSkipFiltering(
-                        getLocalizationTool().format("QueryParserError", 
-                        new SnippetRenderer(data, "TextQueryHelp.vm"))));
-            }
-            else 
-            {
-                queryResults = Collections.EMPTY_LIST;
-                L10NMessage l10nMessage = new L10NMessage(L10NKeySet.ErrorProcessingQuery,e);
-                setAlertMessage(l10nMessage);
-                Log.get().info("Error processing a query", e);
-            }
+            throw new RuntimeException(e);
         }
         
         return queryResults;

Modified: trunk/src/java/org/tigris/scarab/tools/localization/L10NKeySet.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/tools/localization/L10NKeySet.java?view=diff&rev=10486&p1=trunk/src/java/org/tigris/scarab/tools/localization/L10NKeySet.java&p2=trunk/src/java/org/tigris/scarab/tools/localization/L10NKeySet.java&r1=10485&r2=10486
==============================================================================
--- trunk/src/java/org/tigris/scarab/tools/localization/L10NKeySet.java	(original)
+++ trunk/src/java/org/tigris/scarab/tools/localization/L10NKeySet.java	2007-12-04 08:00:13-0800
@@ -204,7 +204,8 @@
     public static final LocalizationKey UserCreated = new L10NKey("UserCreated");
     public static final LocalizationKey ReportNameNotUnique = new L10NKey("ReportNameNotUnique");
     public static final LocalizationKey LockedIssueType = new L10NKey("LockedIssueType");
-    public static final LocalizationKey SearchIndexDoNoteLeavePage = new L10NKey("SearchIndexDoNoteLeavePage");
+    public static final LocalizationKey SearchIndexRebuildInProgress = new L10NKey("SearchIndexRebuildInProgress");
+    public static final LocalizationKey SearchIndexRebuildCancelled = new L10NKey("SearchIndexRebuildCancelled");
     public static final LocalizationKey HeadingRemoved = new L10NKey("HeadingRemoved");
     public static final LocalizationKey NoPredefinedXModuleListSelected = new L10NKey("NoPredefinedXModuleListSelected");
     public static final LocalizationKey IssueTypeNameExists = new L10NKey("IssueTypeNameExists");

Modified: trunk/src/java/org/tigris/scarab/util/word/IssueSearch.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/util/word/IssueSearch.java?view=diff&rev=10486&p1=trunk/src/java/org/tigris/scarab/util/word/IssueSearch.java&p2=trunk/src/java/org/tigris/scarab/util/word/IssueSearch.java&r1=10485&r2=10486
==============================================================================
--- trunk/src/java/org/tigris/scarab/util/word/IssueSearch.java	(original)
+++ trunk/src/java/org/tigris/scarab/util/word/IssueSearch.java	2007-12-04 08:00:13-0800
@@ -78,7 +78,6 @@
 import org.tigris.scarab.attribute.StringAttribute;
 import org.tigris.scarab.om.ActivityPeer;
 import org.tigris.scarab.om.ActivitySetPeer;
-import org.tigris.scarab.om.AttachmentTypePeer;
 import org.tigris.scarab.om.Attribute;
 import org.tigris.scarab.om.AttributeManager;
 import org.tigris.scarab.om.AttributeOption;
@@ -437,17 +436,6 @@
         {
             textScope = getTextScopeForAll();
         }
-        else
-        {
-            for (int i = textScope.length - 1; i >= 0; i--)
-            {
-                if (NUMBERKEY_0.equals(textScope[i])) 
-                {
-                    textScope = getTextScopeForAll();
-                    break;
-                }       
-            }
-        }
         return textScope;
     }
 
@@ -1041,90 +1029,108 @@
         }
     }
 
-    private Long[] getTextMatches()
+    private List getTextMatches()
         throws Exception
     {
-        List setAttValues = getSetAttributeValues();
-    	boolean searchCriteriaExists = false;
-        Long[] matchingIssueIds = null;
-        SearchIndex searchIndex = SearchFactory.getInstance();
+        TextQuery query = new  TextQuery();
 
-        if (getSearchWords() != null && getSearchWords().length() != 0)
+        if (isSimpleTextQuery())
         {
-            searchIndex.addQuery(getTextScope(), getSearchWords());
-            searchCriteriaExists = true;
+            query.addAttrClauses(getSimpleTextClauses());
         }
         else 
         {
-            for (int i=0; i<setAttValues.size(); i++) 
+            List setAttValues = getSetAttributeValues();
+            for (Iterator i = setAttValues.iterator(); i.hasNext();) 
             {
-                AttributeValue aval = (AttributeValue)setAttValues.get(i);
+                AttributeValue aval = (AttributeValue)i.next();
 
-                Integer[] ids = {aval.getAttributeId()};
-
-                //FIXME remove auxDate workaround for date ranges
                 if (aval instanceof DateAttribute)
                 {
-                    searchCriteriaExists = true;
-                    AttributeValue auxAval = aval.getChainedValue();
-
-                    Date date = parseDate(aval.getValue(), false); 
-                    Date auxDate = date;
-                    if(auxAval != null &&
-                       emptyString2null(auxAval.getValue()) != null)
-                    {
-                    	auxDate = parseDate(auxAval.getValue(), true);                        	
-                    }                        
-                    if (date.equals(auxDate))
-                    {    
-                    	searchIndex.addQuery(ids, DateAttribute.internalDateFormat(date));
-                    }
-                    else
-                    {
-                        searchIndex.addQuery(ids, 
-                            SearchIndex.TEXT + ":["
-                            +DateAttribute.internalDateFormat(date) 
-                            + " TO " 
-                            + DateAttribute.internalDateFormat(auxDate) 
-                            + "]"
-                        );
-                    }
+                    query.addAttrClause(getDateAttributeClause(aval));
                 }
                 else if (aval instanceof StringAttribute)
                 {
-                    searchCriteriaExists = true;
-                    searchIndex.addQuery(ids, aval.getValue());
+                    query.addAttrClause(aval);
                 }
             }
         }
 
-        // add comment attachments
-        String commentQuery = getCommentQuery();
-        if (commentQuery != null && commentQuery.trim().length() > 0) 
-        {
-            Integer[] id = {AttachmentTypePeer.COMMENT_PK};
-            searchIndex.addAttachmentQuery(id, commentQuery);            
-            searchCriteriaExists = true;
-        }
+        query.addCommentClause(getCommentQuery());
+        
+        query.setAnd(!getMergePartialTextQueries());
 
-        if (searchCriteriaExists) 
+        List matchingIssueIds = null;
+        if(!query.isEmpty())
         {
+            LuceneSearchIndex LuceneSearchIndex = SearchFactory.getInstance();
             try 
             {
-                matchingIssueIds = searchIndex.getRelatedIssues(getMergePartialTextQueries());    
+                matchingIssueIds = LuceneSearchIndex.executeQuery(query);    
             }
-            catch (Exception e)
+            finally
             {
-                SearchFactory.releaseInstance(searchIndex);
-                throw e;
+                SearchFactory.releaseInstance(LuceneSearchIndex);
             }
         }
-
-        SearchFactory.releaseInstance(searchIndex);
-        
         return matchingIssueIds;
     }
 
+    private AttributeValue getDateAttributeClause(AttributeValue aval) 
+        throws Exception
+    {
+        //FIXME remove auxDate workaround for date ranges
+        AttributeValue auxAval = aval.getChainedValue();
+
+        Date date = parseDate(aval.getValue(), false); 
+        Date auxDate = date;
+        if(auxAval != null &&
+           emptyString2null(auxAval.getValue()) != null)
+        {
+        	auxDate = parseDate(auxAval.getValue(), true);                        	
+        }
+        String clause;
+        if (date.equals(auxDate))
+        {    
+        	clause = DateAttribute.internalDateFormat(date);
+        }
+        else
+        {
+            clause =
+                "[" + DateAttribute.internalDateFormat(date) + " TO " 
+                    + DateAttribute.internalDateFormat(auxDate) + "]"
+            ;
+      
+        }
+        StringAttribute clauseAV = new StringAttribute();
+        clauseAV.setAttributeId(aval.getAttributeId());
+        clauseAV.setValue(clause);
+        return clauseAV;
+    }
+
+    private List getSimpleTextClauses() throws Exception
+    {
+        String clause = getSearchWords();
+        List textClauses = new ArrayList();
+        Integer[] attributeIds = getTextScope();
+        
+        for(int i=0;i<attributeIds.length;i++){
+            StringAttribute clauseAV = new StringAttribute();
+            clauseAV.setAttributeId(attributeIds[i]);
+            clauseAV.setValue(clause);
+            textClauses.add(clauseAV);
+            
+        }
+        return textClauses;
+    }
+
+    private boolean isSimpleTextQuery()
+    {
+        return 
+           getSearchWords() != null 
+           && getSearchWords().length() != 0;
+    }
+
     private static String useAlias(String alias, String tableColumn)
     {
         int dot = tableColumn.indexOf('.');
@@ -1144,11 +1150,11 @@
         mitList.addToCriteria(crit);
     }
 
-    private void addMatchedTextCriteria(Criteria crit, Long[] issueIdsMatchedText)
+    private void addMatchedTextCriteria(Criteria crit, List issueIdsMatchedText)
     {
         if(issueIdsMatchedText!=null)
-        {
-    	    crit.andIn(IssuePeer.ISSUE_ID, issueIdsMatchedText);
+        {    	    
+            crit.andIn(IssuePeer.ISSUE_ID, issueIdsMatchedText);
         }
     }
 
@@ -1297,7 +1303,7 @@
         crit.addAscendingOrderByColumn(IssuePeer.ISSUE_ID);
     }
     
-    private Criteria getCoreSearchCriteria(Long[] issueIdsMatchedText)
+    private Criteria getCoreSearchCriteria(List issueIdsMatchedText)
         throws java.lang.Exception
     {
         Criteria crit = new Criteria();
@@ -1697,9 +1703,9 @@
         Criteria c = null;
     	if (isSearchAllowed) 
         {
-            Long[] issueIdsMatchedText = getTextMatches();
+            List issueIdsMatchedText = getTextMatches();
             
-            if (issueIdsMatchedText==null || issueIdsMatchedText.length > 0) 
+            if (issueIdsMatchedText==null || issueIdsMatchedText.size() > 0) 
             {            
             	c = getCoreSearchCriteria(issueIdsMatchedText);
             }

Modified: trunk/src/java/org/tigris/scarab/util/word/LuceneSearchIndex.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/util/word/LuceneSearchIndex.java?view=diff&rev=10486&p1=trunk/src/java/org/tigris/scarab/util/word/LuceneSearchIndex.java&p2=trunk/src/java/org/tigris/scarab/util/word/LuceneSearchIndex.java&r1=10485&r2=10486
==============================================================================
--- trunk/src/java/org/tigris/scarab/util/word/LuceneSearchIndex.java	(original)
+++ trunk/src/java/org/tigris/scarab/util/word/LuceneSearchIndex.java	2007-12-04 08:00:13-0800
@@ -50,45 +50,43 @@
 import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Map;
 
 import org.apache.avalon.framework.activity.Initializable;
-import org.apache.avalon.framework.configuration.Configurable;
-import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.activity.Disposable;
 import org.apache.avalon.framework.context.Context;
 import org.apache.avalon.framework.context.ContextException;
 import org.apache.avalon.framework.context.Contextualizable;
+import org.apache.commons.configuration.Configuration;
+import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.index.CorruptIndexException;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.Term;
+import org.apache.lucene.queryParser.ParseException;
 import org.apache.lucene.queryParser.QueryParser;
+import org.apache.lucene.search.Hit;
 import org.apache.lucene.search.Hits;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.Query;
+import org.apache.lucene.store.FSDirectory;
+import org.apache.lucene.store.NativeFSLockFactory;
+import org.apache.torque.TorqueException;
 import org.apache.torque.util.Criteria;
-import org.apache.turbine.RunData;
-import org.apache.turbine.TemplateContext;
-import org.tigris.scarab.actions.admin.UpdateSearchIndex.UpdateThread;
+import org.apache.turbine.Turbine;
+import org.tigris.scarab.attribute.StringAttribute;
 import org.tigris.scarab.om.Attachment;
-import org.tigris.scarab.om.AttachmentPeer;
+import org.tigris.scarab.om.AttachmentTypePeer;
 import org.tigris.scarab.om.AttributeValue;
-import org.tigris.scarab.om.AttributeValuePeer;
+import org.tigris.scarab.om.Issue;
 import org.tigris.scarab.om.IssuePeer;
-import org.tigris.scarab.tools.ScarabLocalizationTool;
-import org.tigris.scarab.tools.ScarabRequestTool;
 import org.tigris.scarab.tools.localization.L10NKeySet;
-import org.tigris.scarab.tools.localization.L10NMessage;
-import org.tigris.scarab.tools.localization.Localizable;
 import org.tigris.scarab.util.Log;
 import org.tigris.scarab.util.ScarabException;
 
-import com.workingdogs.village.Record;
-
 /**
  * Support for searching/indexing text
  *
@@ -96,559 +94,162 @@
  * @version $Id$
  */
 public class LuceneSearchIndex 
-    implements SearchIndex, Configurable,Contextualizable,Initializable
+    implements Contextualizable,Initializable,Disposable
 {
-    private String applicationRoot;
-    // used to occasionally optimize the index
-    private static int counter = 0;
-
-    /** the location of the index */
-    private String path;
-
-    /** the attributes that will be searched */
-    private List attributeIds;
+    private static final String INDEX_PATH = "path";
+    private static final String ANALYZER_CLASS = "analyzerClass";
+    private static final String ISSUE_ID = "issueId";
 
-    /** the words and boolean operators */
-    private List queryText;
+    static final String COMMENT = "comment";
+    static final String ATTRIBUTE_ID = "attributeId";
 
-    /** the attachments that will be searched */
-    private List attachmentIds;
+    private String applicationRoot;
 
-    /** the words and boolean operators */
-    private List attachmentQueryText;
+    private FSDirectory indexDir;
+    private IndexWriter writer;
+    private Analyzer analyzer;
+    private long updateCounter = 0;
     
-    static private ThreadGroup tg = null;
+    private Thread rebuildThread;
+    private RebuildMonitor rebuildMonitor;
 
-    /**
-     * Ctor.  Sets up an index directory if one does not yet exist in the
-     * path specified by searchindex.path property in Scarab.properties.
-     */
     public LuceneSearchIndex()
-        throws IOException
-    {
-        
-        
-    }
-
-    public void addQuery(Integer[] ids, String text)
-    {
-        attributeIds.add(ids);
-        queryText.add(text);
-    }
-
-    public void addAttachmentQuery(Integer[] ids, String text)
     {
-        attachmentIds.add(ids);
-        attachmentQueryText.add(text);
-    }
-
-    public Long[] getRelatedIssues()
-    throws Exception
-    {
-        return getRelatedIssues(false); // perform AND operation
     }
 
     /**
      *  returns a list of related issue IDs sorted by relevance descending.
      *  Should return an empty/length=0 array if search returns no results.
-     *  If mergeResults==true, internally merges results of partial queries,
-     *  otherwise performs an implicit AND operation on partial queries.
      */
-    public Long[] getRelatedIssues(boolean mergeResults) 
+    public List executeQuery(TextQuery textQuery) 
         throws Exception
     {
-        Long[] result;
-        List issueIds = null; 
-        // if there are no words to search for return no results 
-        if (queryText.size() != 0 || attachmentQueryText.size() != 0)
-        {
-            // attributes
-            for (int j=attributeIds.size()-1; j>=0; j--) 
-            {
-                Integer[] ids = (Integer[])attributeIds.get(j);
-                String query = (String) queryText.get(j);
-                issueIds = performPartialQuery(ATTRIBUTE_ID, 
-                                               ids, query, issueIds,
-                                               mergeResults);
-            }
-
-            // attachments
-            for (int j=attachmentIds.size()-1; j>=0; j--) 
-            {
-                Integer[] ids = (Integer[])attachmentIds.get(j);
-                String query = (String) attachmentQueryText.get(j);
-                issueIds = performPartialQuery(ATTACHMENT_TYPE_ID, 
-                                               ids, query, issueIds,
-                                               mergeResults);
-            }
-
-            // put results into final form
-            result = new Long[issueIds.size()];
-            for (int i=0; i<issueIds.size(); i++) 
-            {
-                result[i] = (Long)issueIds.get(i);
-            }
-        }
-        else
+        String queryText = textQuery.toString();
+        
+        Query luceneQuery;
+        try
         {
-            result = EMPTY_LIST; 
+           luceneQuery = new QueryParser("", analyzer).parse(queryText);
         }
-        
-        return result;
-    }
-
-    private List performPartialQuery(String key, Integer[] ids, 
-                                     String query, List issueIds,
-                                     boolean mergeResults)
-        throws ScarabException, IOException
-    {
-        StringBuffer fullQuery = new StringBuffer(query.length()+100);
-        
-        if (query.length() > 0)
+        catch (ParseException e)
         {
-            query.trim();
+            throw new ScarabException( L10NKeySet.ExceptionParseError, queryText, e);
         }
-        
-                if (ids != null && ids.length != 0) 
-                {
-                    fullQuery.append("+((");
-                    for (int i=ids.length-1; i>=0; i--) 
-                    {
-                        fullQuery.append(key)
-                            .append(':')
-                            .append(ids[i].toString());
-                        if (i != 0) 
-                        {
-                            fullQuery.append(" OR ");
-                        }
-                    }
-                    fullQuery.append(") AND (")
-                        .append(query)
-                        .append("))");            
-                }
-                else
-                {
-                    fullQuery
-                        .append("+(")
-                        .append(query)
-                        .append(')');
-                }
-                
-                Query q = null;
-                try
-                {
-                    Log.get().debug("Querybefore=" + fullQuery);
-                    q = QueryParser.parse(fullQuery.toString(), TEXT, 
-                                          new PorterStemAnalyzer());
-                    Log.get().debug("Queryafter=" + q.toString("text"));
-                }
-                catch (Throwable t)
-                {
-                    throw new ScarabException(
-                            L10NKeySet.ExceptionParseError,
-                            fullQuery,
-                            t);
-                }
-                
-                IndexSearcher is = new IndexSearcher(path); 
-                Hits hits = is.search(q);
-                // remove duplicates
-                Map deduper = new HashMap((int)(1.25*hits.length()+1));
-                for (int i=0; i<hits.length(); i++) 
-                {
-                    deduper.put(hits.doc(i).get(ISSUE_ID), null);
-                    Log.get().debug("Possible issueId from search: " + 
-                                  hits.doc(i).get(ISSUE_ID));
-                }
-                is.close();
-                
-                if (issueIds == null) 
-                {
-                    issueIds = new ArrayList(deduper.size());
-                    Iterator iter = deduper.keySet().iterator();
-                    while (iter.hasNext()) 
-                    {
-                        issueIds.add(new Long((String)iter.next()));
-                        Log.get().debug("Adding issueId from search: " + 
-                                  issueIds.get(issueIds.size()-1));
-                    }
-                }
-                else 
-                {
-                    if (mergeResults)
-                    {
-                        // perform OR operation
-                        mergeResults(issueIds, deduper);
-                    }
-                    else
-                    {
-                        // perform an AND operation
-                        removeUniqueElements(issueIds, deduper);
-                    }
-                }
-        return issueIds;
-    }
 
-    /**
-     * Elements from the list that are not in map are removed from the list
-     */
-    private void removeUniqueElements(List list, Map map)
-    {
-        for (int i=list.size()-1; i>=0; i--) 
+        List issueIds = new ArrayList();
+        IndexSearcher is = new IndexSearcher(indexDir); 
+        try
         {
-            Object obj = list.get(i);
-            if (!map.containsKey(obj.toString())) 
+            Hits hits = is.search(luceneQuery);
+            
+            for(Iterator hi = hits.iterator(); hi.hasNext();)
             {
-                Log.get().debug("removing issueId from search: " + obj);
-                list.remove(i);
+                Hit h = (Hit)hi.next();
+                issueIds.add( Long.valueOf(h.get(ISSUE_ID)));
             }
         }
+        finally
+        {
+            is.close();
+        }        
+        return issueIds;
     }
 
-    /**
-     * Elements from the map, which are not in list are added to the list
-     */
-    private void mergeResults(List list, Map map)
+    public void index(Issue issue)
+    throws Exception
     {
-        for (int i=list.size()-1; i>=0; i--) 
+        Document doc = document(issue);
+        synchronized(this)
         {
-            Long issueId = (Long)list.get(i);
-            String id = issueId.toString();
-            if (map.containsKey(id)) 
-            {
-                map.remove(id);
-                Log.get().debug("removed duplicate issueId from map: " + id);
-            }
-        }
-        Iterator iter = map.keySet().iterator();
-        while(iter.hasNext())
-        {
-            String id = (String)iter.next();
-            list.add(new Long(Long.parseLong(id)));
-            Log.get().debug("Add issueId from map to List: " + id);
+            update(doc);
+            optimize(false);
+            flush();
         }
     }
 
+    private void update(Document doc)
+    throws Exception
+    {    
+        writer.updateDocument(new Term( ISSUE_ID, doc.get(ISSUE_ID) ), doc); 
+    }
 
-    /**
-     * Store index information for an AttributeValue
-     */
-    public void index(AttributeValue attributeValue)
-        throws Exception
+    private void flush() throws CorruptIndexException, IOException
     {
-        String valId = attributeValue.getValueId().toString();
-
-        // make sure any old data stored for this attribute value is deleted.
-        Term term = new Term(VALUE_ID, valId);
-        int deletedDocs = 0;
-        try
-        {
-            synchronized (getClass())
-            {
-                IndexReader reader = null;
-                try
-                {
-                    reader = IndexReader.open(path);
-                    deletedDocs = reader.delete(term);
-                }
-                finally
-                {
-                    if (reader != null) 
-                    {
-                        reader.close();
-                    }
-                }
-            }
-        }
-        catch (NullPointerException npe)
-        {
-            /* Lucene is throwing npe in reader.delete, so have to explicitely
-               search.  Not sure if the npe will be thrown in the 
-               case where the attribute has previously been indexed, so
-               test whether the npe is harmful.
-            */
-            IndexSearcher is = new IndexSearcher(path); 
-            Query q = QueryParser.parse("+" + VALUE_ID + ":" + valId, TEXT, 
-                                        new PorterStemAnalyzer());
-            Hits hits = is.search(q);
-            if (hits.length() > 0) 
-            {
-                Localizable l10nInstance = new L10NMessage(L10NKeySet.ExceptionLucene, valId, npe);
-                Log.get().debug(l10nInstance.getMessage());//[HD: create english message for logging!
-                throw new ScarabException(l10nInstance);
-            }
-        }
-        if (deletedDocs > 1) 
-        {
-            throw new ScarabException(L10NKeySet.ExceptionMultipleAttValues,
-                                      valId);
-        }
-        /*
-        System.out.println("deleting valId: " + valId);
-        IndexSearcher is = new IndexSearcher(path); 
-        Hits hits = is.search("+" + VALUE_ID + ":" + valId);
-        System.out.println("deleting previous: " + hits.length());
-        if (hits.length() > 1) 
-        {
-            throw new ScarabException("Multiple AttributeValues in Lucene" +
-                                      "index with same ValueId: " + valId);
-        }
-        Document doc = hits.doc(0);
-        */
-
-        if (attributeValue.getValue() == null) 
-        {
-            Log.get().warn("Attribute value pk=" + valId + 
-                           " has a null value.");
-        }
-        else 
-        {
-            Document doc = new Document();
-            Field valueId = Field.Keyword(VALUE_ID, valId);
-            Field issueId = Field.UnIndexed(ISSUE_ID, 
-                attributeValue.getIssueId().toString());
-            Field attributeId = Field.Keyword(ATTRIBUTE_ID, 
-                attributeValue.getAttributeId().toString());
-            Field text = Field.UnStored(TEXT, attributeValue.getValue());
-            doc.add(valueId);
-            doc.add(issueId);
-            doc.add(attributeId);
-            doc.add(text);
-            addDoc(doc);
-        }    
+        writer.flush();
     }
 
-    private void addDoc(Document doc)
-        throws IOException
+    private void optimize(boolean immediately) throws CorruptIndexException, IOException
     {
-        synchronized (getClass())
+        if(immediately || updateCounter  % 100 == 0)
         {
-            IndexWriter indexer = null;
-            try
-            {
-                indexer = new IndexWriter(path, 
-                                          new PorterStemAnalyzer(), false);
-                indexer.addDocument(doc);
-                
-                if (++counter % 100 == 0) 
-                {
-                    indexer.optimize();
-                }
-            }
-            finally
-            {
-                if (indexer != null) 
-                {
-                    indexer.close();                    
-                }
-            }
+            writer.optimize();
         }
-    }        
+        updateCounter++;
+    }
+    
+    private void close() throws CorruptIndexException, IOException
+    {
+        writer.close();
+    }
 
-    /**
-     * Store index information for an Attachment
-     */
-    public void index(Attachment attachment)
-        throws Exception
+    private Document document(Issue issue)
+            throws TorqueException
     {
-        String attId = attachment.getAttachmentId().toString();
+        String issueId = issue.getIssueId().toString();
+        Document doc = new Document();
+        doc.add(new Field( ISSUE_ID, issueId, Field.Store.YES, Field.Index.UN_TOKENIZED ));
 
-        // make sure any old data stored for this attribute value is deleted.
-        Term term = new Term(ATTACHMENT_ID, attId);
-        int deletedDocs = 0;
-        try
+        for(Iterator as = issue.getAttachments().iterator(); as.hasNext();)
         {
-            synchronized (getClass())
+            Attachment a = (Attachment)as.next();
+            if (    a.getTypeId().equals(AttachmentTypePeer.COMMENT_PK)
+                && !a.getDeleted()) 
             {
-                IndexReader reader = null;
-                try
-                {
-                    reader = IndexReader.open(path);
-                    deletedDocs = reader.delete(term);
-                }
-                finally
-                {
-                    if (reader != null) 
-                    {
-                        reader.close();
-                    }
-                }
+                doc.add(new Field( COMMENT, a.getData(), Field.Store.YES, Field.Index.TOKENIZED ));                
             }
         }
-        catch (NullPointerException npe)
+        
+        for(Iterator vs = issue.getAttributeValuesMap().values().iterator(); vs.hasNext();)
         {
-            /* Lucene is throwing npe in reader.delete, so have to explicitely
-               search.  Not sure if the npe will be thrown in the 
-               case where the attribute has previously been indexed, so
-               test whether the npe is harmful.
-            */
-            IndexSearcher is = new IndexSearcher(path); 
-            Query q = QueryParser.parse("+" + ATTACHMENT_ID + ":" + attId, 
-                                        TEXT, new PorterStemAnalyzer());
-            Hits hits = is.search(q);
-            if (hits.length() > 0) 
+            AttributeValue v = (AttributeValue)vs.next();
+            if(    v instanceof StringAttribute
+               && !v.getDeleted())
             {
-                Localizable l10nInstance = new L10NMessage(L10NKeySet.ExceptionLucene, attId, npe);
-                Log.get().debug(l10nInstance.getMessage());//[HD: create english message for logging!
-                throw new ScarabException(l10nInstance);
+                doc.add(new Field( ATTRIBUTE_ID + v.getAttributeId().toString(), v.getValue(), Field.Store.YES, Field.Index.TOKENIZED ));
             }
         }
-        if (deletedDocs > 1) 
-        {
-            throw new ScarabException(L10NKeySet.ExceptionMultipleAttachements,
-                                      attId);
-        }
-
-
-        if (attachment.getData() == null) 
-        {
-            Log.get().warn("Attachment pk=" + attId + " has a null data.");
-        }
-        else 
-        {
-            Document doc = new Document();
-            Field attachmentId = Field.Keyword(ATTACHMENT_ID, attId);
-            Field issueId = Field.UnIndexed(ISSUE_ID, 
-                attachment.getIssueId().toString());
-            Field typeId = Field.Keyword(ATTACHMENT_TYPE_ID, 
-                attachment.getTypeId().toString());
-            Field text = Field.UnStored(TEXT, attachment.getData());
-            doc.add(attachmentId);
-            doc.add(issueId);
-            doc.add(typeId);
-            doc.add(text);
-            addDoc(doc);
-        }            
+        return doc;
     }
 
     /**
      * update the index for all entities that currently exist
+     * @param rebuildMonitor 
      */
-    public void updateIndex()
+    private void rebuild(RebuildMonitor rebuildMonitor)
         throws Exception
-    {
-        Log.get().info("find estimate of max id...");
-        Criteria crit = new Criteria();
-        crit.addSelectColumn("max(" + AttributeValuePeer.VALUE_ID + ")");
-        List records = AttributeValuePeer.doSelectVillageRecords(crit);
-        long max = ((Record)records.get(0)).getValue(1).asLong();
-        
-        long i = 0L;
-        List avs = null;
-        
-        Log.get().info("index attribute values in database ...");
-        do
-        {
-            crit = new Criteria();
-            Criteria.Criterion low = crit.getNewCriterion(
-                 AttributeValuePeer.VALUE_ID, 
-                 new Long(i), Criteria.GREATER_THAN);
-            i += 100L;
-            Criteria.Criterion high = crit.getNewCriterion(
-                AttributeValuePeer.VALUE_ID, 
-                new Long(i), Criteria.LESS_EQUAL);
-            crit.add(low.and(high));
-            crit.add(AttributeValuePeer.DELETED, false);
-            // don't index issues that have been deleted
-            crit.addJoin(AttributeValuePeer.ISSUE_ID, IssuePeer.ISSUE_ID);
-            crit.add(IssuePeer.DELETED, false);
-            avs = AttributeValuePeer.doSelect(crit);
-            if (!avs.isEmpty()) 
-            {
-                Iterator avi = avs.iterator();
-                while (avi.hasNext()) 
-                {
-                    AttributeValue av = (AttributeValue)avi.next();
-                    index(av);
-                }
-                if (Log.get().isDebugEnabled()) 
-                {
-                    Log.get().debug("Updated index for attribute values (" + 
-                        (i-100L) + "-" + i + "]");                    
-                    Log.debugMemory();
-                }                
-            }  
-        }
-        while (i<max || !avs.isEmpty());
-
-        Log.get().info("Index attachments ...");// Attachments
-
-        crit = new Criteria();
-        crit.addSelectColumn("max(" + AttachmentPeer.ATTACHMENT_ID + ")");
-        records = AttachmentPeer.doSelectVillageRecords(crit);
-        max = ((Record)records.get(0)).getValue(1).asLong();
-        i = 0L;
-        List atts = null;
-        do
-        {
-            crit = new Criteria();
-            Criteria.Criterion low = crit.getNewCriterion(
-                 AttachmentPeer.ATTACHMENT_ID, 
-                 new Long(i), Criteria.GREATER_THAN);
-            i += 100L;
-            Criteria.Criterion high = crit.getNewCriterion(
-                AttachmentPeer.ATTACHMENT_ID, 
-                new Long(i), Criteria.LESS_EQUAL);
-            crit.add(low.and(high));
-            crit.add(AttachmentPeer.DELETED, false);
-            // don't index issues that have been deleted
-            crit.addJoin(AttachmentPeer.ISSUE_ID, IssuePeer.ISSUE_ID);
-            crit.add(IssuePeer.DELETED, false);
-            atts = AttachmentPeer.doSelect(crit);
-            if (!atts.isEmpty()) 
-            {
-                Iterator atti = atts.iterator();
-                while (atti.hasNext()) 
-                {
-                    Attachment att = (Attachment)atti.next();
-                    if (att.getData() != null && att.getData().length() > 0 &&
-                        att.getIssueId() != null && att.getTypeId() != null) 
-                    {
-                        index(att);
-                    }                    
-                }
-                
-                if (Log.get().isDebugEnabled()) 
-                {
-                    Log.get().debug("Updated index for attachments (" + 
-                        (i-100L) + "-" + i + "]");                    
-                    Log.debugMemory();
-                }                
-            }  
-        }
-        while (i<max || !atts.isEmpty());
-
-        Log.get().info("Finish off with an optimized index...");
-        synchronized (getClass())
-        {
-            IndexWriter indexer = null;
-            try
-            {
-                indexer = new IndexWriter(path, 
-                                          new PorterStemAnalyzer(), false);
-                indexer.optimize();
-            }
-            finally
-            {
-                if (indexer != null) 
-                {
-                    indexer.close();                    
-                }
-            }
-        }        
-        Log.get().info("Indexing terminated.");
-    }
-    
-    // ---------------- Avalon Lifecycle Methods ---------------------
-    /**
-     * Avalon component lifecycle method
-     */
-    public void configure(Configuration conf) 
-    {
-        path = conf.getAttribute(INDEX_PATH, null);
+    {        
+        Criteria crit = new Criteria()
+            .add(IssuePeer.DELETED, false);
         
-      
+        List issues = IssuePeer.doSelect(crit);
+        rebuildMonitor.setNoIssues(issues.size());
         
+        for(Iterator issuei = issues.iterator(); issuei.hasNext();) 
+        {            
+            Document doc = document((Issue)issuei.next());
+            synchronized(this){
+                update(doc);                
+                rebuildMonitor.issueProcessed();
+            }
+            
+            if(rebuildMonitor.iscancelled()) return;
+        }  
+
+        synchronized(this)
+        {
+            optimize(true);        
+            flush();
+        }
     }
     
     /**
@@ -667,122 +268,164 @@
      *
      * @throws InitializationException if initialization fails.
      */
-    public void initialize() throws Exception
+    public void initialize()
+        throws Exception
     {
+        Configuration cfg = Turbine.getConfiguration().subset("searchindex");
+        String indexPath = cfg.getString(INDEX_PATH, null);
+        String analyzerClassName = cfg.getString(ANALYZER_CLASS, null);
+        
+        File absIndexPath = getIndexDir(indexPath, applicationRoot);
+        
+        indexDir = FSDirectory.getDirectory(absIndexPath, new NativeFSLockFactory(absIndexPath));
+        
+        boolean createIndex = !IndexReader.indexExists(indexDir);
+        
+        analyzer = createAnalyzer(analyzerClassName);
 
-   
-        File indexDir = new File(path);
-        if (!indexDir.isAbsolute()) 
-        {
-            path = getRealPath(path);
-            indexDir = new File(path);
-        }          
+        writer = new IndexWriter(indexDir, analyzer, createIndex);
+ 
+        if(createIndex) startRebuild();        
+    }
 
-        boolean createIndex = false;
-        if (indexDir.exists()) 
+    private Analyzer createAnalyzer(String analyzerClassName)
+    {
+        Analyzer analyzer;
+        try
         {
-            int length = indexDir.listFiles().length;
-            if ( length < 3) 
-            {
-                createIndex = true;
-            }       
+            analyzer = (Analyzer)Class.forName(analyzerClassName).newInstance();
         }
-        else 
+        catch( Exception e)
         {
-            indexDir.mkdirs();
-            createIndex = true;
+            analyzer = new PorterStemAnalyzer();
+            Log.get().error("Could not create Lucene Analyzer (" + analyzerClassName + "), using default.", e);
         }
+        return analyzer;
+    }
+    
+    private File getIndexDir(String path, String applicationRoot)
+    {
+        File file = new File(path);
         
-        if (createIndex)
+        if (applicationRoot != null && !file.isAbsolute())
         {
-            Log.get().info("Creating index at '" + path + '\'');
-            synchronized (getClass())
+            return new File(applicationRoot, path).getAbsoluteFile();
+        }
+        else
+        {
+            return file.getAbsoluteFile();
+        }
+    }
+    
+    public void startRebuild()
+    {        
+        synchronized(this)
+        {
+            if(!isRebuildInProgress())
             {
-                doCreateIndex();
+                rebuildMonitor = new RebuildMonitor();
+                rebuildThread = new Thread(rebuildMonitor, "RebuildIndex");
+                rebuildThread.start();
             }
-        }        
-
-        clear();
+        }
     }
-    
-    private String getRealPath(String path)
+
+    public void cancelRebuild()
     {
-        String absolutePath = null;
-        if (applicationRoot == null)
+        try
+        {
+            synchronized(this)
+            {
+                if(isRebuildInProgress())
+                {
+                    rebuildMonitor.cancel();
+                    rebuildThread.join(10000);
+                }
+            }
+        }
+        catch (Exception e)
         {
-            absolutePath = new File(path).getAbsolutePath();
+            throw new RuntimeException(e);
         }
-        else
+    }
+
+    public boolean isRebuildInProgress()
+    {
+        synchronized(this)
         {
-            absolutePath = new File(applicationRoot, path).getAbsolutePath();
+            return rebuildThread!=null && rebuildThread.isAlive();
         }
-        return absolutePath;
     }
 
-    /* (non-Javadoc)
-     * @see org.tigris.scarab.util.word.SearchIndex#clear()
-     */
-    public void clear()
+    public Integer pctRebuildFinished()
     {
-        attributeIds        = new ArrayList(5);
-        queryText           = new ArrayList(5);
-        attachmentIds       = new ArrayList(2);
-        attachmentQueryText = new ArrayList(2);
+        return new Integer(rebuildMonitor.pctFinished());
     }
     
-    public void doCreateIndex()
-            throws Exception
+    private class RebuildMonitor implements Runnable
     {
-        synchronized (this)
-        {
+        private String REBUILDING = "Rebuilding of Lucene index ";
+        private boolean cancelled = false;
+        private int noIssuesProcessed = 0;
+        private int noIssues = 1;
 
+        public void run()
+        {
             try
             {
-                if(tg == null)
-                {
-                    tg = new ThreadGroup("UpdateIndex");
-                }
-                Thread updateThread = new Thread(tg, new UpdateThread());
-                updateThread.start();
+                Log.get().info(REBUILDING + "started");
+                rebuild(this);
+                Log.get().info(REBUILDING + "finished");
             }
             catch (Exception e)
             {
-                Log.get().warn("Could not start SearchIndex initialization:",e); 
-            }
+                Log.get().error(REBUILDING + "failed", e);
+                throw new RuntimeException(e);
+            }            
+        }
 
+        public void issueProcessed()
+        {
+            noIssuesProcessed++;
+            
         }
 
-    }
+        public void setNoIssues(int noIssues)
+        {
+            this.noIssues = noIssues;
+            
+        }
 
-    public class UpdateThread implements Runnable
-    {
-        public void run()
+        public void cancel()
         {
-            try
-            {
-                IndexWriter indexWriter = null;
-                try
-                {
-                    indexWriter = new IndexWriter(path, new PorterStemAnalyzer(), true);
-                }
-                finally
-                {
-                    if (indexWriter != null) 
-                    {
-                        indexWriter.close();                           
-                    }
-                }
+            cancelled = true;
+        }
 
-                Log.get().info("Update index started!");
-                SearchIndex indexer = SearchFactory.getInstance();
-                indexer.updateIndex();            
-                Log.get().info("Update index completed!");
+        public boolean iscancelled()
+        {
+            return cancelled;
+        }
+        
+        public int pctFinished()
+        {
+            return noIssuesProcessed*100/noIssues;
+        }
+    }
 
-            }
-            catch (Exception e)
+    public void dispose()
+    {
+        try
+        {
+            synchronized(this)
             {
-                Log.get().error("Update index failed:", e);
+                cancelRebuild();
+                close();
             }
+        } 
+        catch (Exception e)
+        {
+            throw new RuntimeException(e);
         }
+        
     }
 }

Modified: trunk/src/java/org/tigris/scarab/util/word/PorterStemAnalyzer.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/util/word/PorterStemAnalyzer.java?view=diff&rev=10486&p1=trunk/src/java/org/tigris/scarab/util/word/PorterStemAnalyzer.java&p2=trunk/src/java/org/tigris/scarab/util/word/PorterStemAnalyzer.java&r1=10485&r2=10486
==============================================================================
--- trunk/src/java/org/tigris/scarab/util/word/PorterStemAnalyzer.java	(original)
+++ trunk/src/java/org/tigris/scarab/util/word/PorterStemAnalyzer.java	2007-12-04 08:00:13-0800
@@ -47,18 +47,13 @@
  */
 
 import java.io.Reader;
-import java.io.IOException;
 import org.apache.lucene.analysis.PorterStemFilter;
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.analysis.TokenStream;
-import org.apache.lucene.analysis.Token;
 import org.apache.lucene.analysis.standard.StandardAnalyzer;
-import org.tigris.scarab.util.Log;
 
 public class PorterStemAnalyzer extends Analyzer
 {
-    private static final boolean DEBUG = false;
-
     /** 
      * Constructs a {@link StandardAnalyzer} filtered by a {@link
      * PorterStemFilter}.
@@ -68,38 +63,6 @@
         TokenStream result = new StandardAnalyzer()
             .tokenStream(fieldName, reader);
         result = new PorterStemFilter(result);
-        if (DEBUG) 
-        {
-            final TokenStream delegate = result;
-            result = new TokenStream()
-                {
-                    /** 
-                     * Returns the next token in the stream, or null at EOS. 
-                     */
-                    public Token next() throws IOException
-                    {
-                        Token token = delegate.next();
-                        if (token != null) 
-                        {
-                            if (Log.get().isDebugEnabled()) 
-                            {
-                                Log.get().debug("Token (" + token.type() + 
-                                                "): " + token.termText());
-                            }
-                        }        
-                        return token;
-                    }
-    
-                    /** 
-                     * Releases resources associated with this stream. 
-                     */
-                    public void close() throws IOException 
-                    {
-                        delegate.close();
-                    }
-                };
-        }
-        
         return result;
     }    
 }

Modified: trunk/src/java/org/tigris/scarab/util/word/SearchFactory.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/util/word/SearchFactory.java?view=diff&rev=10486&p1=trunk/src/java/org/tigris/scarab/util/word/SearchFactory.java&p2=trunk/src/java/org/tigris/scarab/util/word/SearchFactory.java&r1=10485&r2=10486
==============================================================================
--- trunk/src/java/org/tigris/scarab/util/word/SearchFactory.java	(original)
+++ trunk/src/java/org/tigris/scarab/util/word/SearchFactory.java	2007-12-04 08:00:13-0800
@@ -52,24 +52,24 @@
 import org.tigris.scarab.util.ScarabRuntimeException;
 
 /**
- * Returns an instance of the SearchIndex specified in Scarab.properties
+ * Returns an instance of the LuceneSearchIndex specified in Scarab.properties
  * 
  * @author <a href="mailto:[email protected]">John D. McNally </a>
  * @version $Id$
  */
 public class SearchFactory {
-    private static SearchIndex searchIndex;
+    private static LuceneSearchIndex LuceneSearchIndex;
 
-    public static SearchIndex getInstance()  
+    public static LuceneSearchIndex getInstance()  
     {
-        SearchIndex result = searchIndex;
+        LuceneSearchIndex result = LuceneSearchIndex;
 
         if (result == null) 
         {
             
             try{
                 ServiceManager sm = ServiceManager.getInstance();
-                return (SearchIndex) sm.lookup(SearchIndex.class);
+                return (LuceneSearchIndex) sm.lookup(LuceneSearchIndex.class);
             } 
             catch (Exception e) {
                 throw new ScarabRuntimeException(L10NKeySet.ExceptionLucene, e);
@@ -79,24 +79,23 @@
     }
 
     /**
-     * Release a searchIndex after it as been looked up from @getInstance()
-     * @param searchIndex
+     * Release a LuceneSearchIndex after it as been looked up from @getInstance()
+     * @param LuceneSearchIndex
      */
-    public static void releaseInstance(SearchIndex searchIndex) 
+    public static void releaseInstance(LuceneSearchIndex LuceneSearchIndex) 
     {
         YaafiComponentService yaafi = ServiceManager.getService();
-        searchIndex.clear();
-        yaafi.release(searchIndex);
+        yaafi.release(LuceneSearchIndex);
     }
 
 
     /**
      * Needed for unit testing only
-     * @param searchIndex
+     * @param LuceneSearchIndex
      */
-    public static void setSearchIndex(SearchIndex searchIndex)
+    public static void setLuceneSearchIndex(LuceneSearchIndex LuceneSearchIndex)
     {
-        SearchFactory.searchIndex = searchIndex;
+        SearchFactory.LuceneSearchIndex = LuceneSearchIndex;
     }
     
 }

Removed: trunk/src/java/org/tigris/scarab/util/word/SearchIndex.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/util/word/SearchIndex.java?view=auto&rev=10485

Modified: trunk/src/test/org/tigris/scarab/util/word/LuceneSearchIndexTest.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/test/org/tigris/scarab/util/word/LuceneSearchIndexTest.java?view=diff&rev=10486&p1=trunk/src/test/org/tigris/scarab/util/word/LuceneSearchIndexTest.java&p2=trunk/src/test/org/tigris/scarab/util/word/LuceneSearchIndexTest.java&r1=10485&r2=10486
==============================================================================
--- trunk/src/test/org/tigris/scarab/util/word/LuceneSearchIndexTest.java	(original)
+++ trunk/src/test/org/tigris/scarab/util/word/LuceneSearchIndexTest.java	2007-12-04 08:00:13-0800
@@ -69,7 +69,7 @@
         super(arg0);
     }
 
-    private SearchIndex searchIndex = null;
+    private LuceneSearchIndex LuceneSearchIndex = null;
 
 	/*
 	 * @see TestCase#setUp()
@@ -77,8 +77,8 @@
 	public void testLookup() throws Exception {
 		super.setUp();
         
-		searchIndex = (SearchIndex)this.lookup(SearchIndex.class.getName());
-        assertNotNull(searchIndex);
+		LuceneSearchIndex = (LuceneSearchIndex)this.lookup(LuceneSearchIndex.class.getName());
+        assertNotNull(LuceneSearchIndex);
 
 		
 	}

Modified: trunk/src/webapp/WEB-INF/templates/screens/admin/UpdateSearchIndex.vm
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/webapp/WEB-INF/templates/screens/admin/UpdateSearchIndex.vm?view=diff&rev=10486&p1=trunk/src/webapp/WEB-INF/templates/screens/admin/UpdateSearchIndex.vm&p2=trunk/src/webapp/WEB-INF/templates/screens/admin/UpdateSearchIndex.vm&r1=10485&r2=10486
==============================================================================
--- trunk/src/webapp/WEB-INF/templates/screens/admin/UpdateSearchIndex.vm	(original)
+++ trunk/src/webapp/WEB-INF/templates/screens/admin/UpdateSearchIndex.vm	2007-12-04 08:00:13-0800
@@ -9,12 +9,13 @@
 $l10n.UpdateSearchIndexBody
 </p>
 
-#if (!$updateFrequency || $updateFrequency.length() == 0)
- <div class="functnbar2">
-   <input type="submit" value="$l10n.UpdateSearchIndex" name="eventSubmit_doSubmit" 
-   onclick="eventSubmit_doSubmit.disabled=true;document.updatesearchindex.submit()" />
- </div>
+<div class="functnbar2">
+#if ($rebuildInProgress)
+   <input type="submit" value="$l10n.Cancel" name="eventSubmit_doCancel" />
+#else
+   <input type="submit" value="$l10n.UpdateSearchIndex" name="eventSubmit_doPerform" />
 #end
+ </div>
 
 </form>
 </div>

Removed: trunk/www/repository/lucene/jars/lucene-1.2.jar
Url: http://scarab.tigris.org/source/browse/scarab/trunk/www/repository/lucene/jars/lucene-1.2.jar?view=auto&rev=10485

Added: trunk/www/repository/lucene/jars/lucene-analyzers-2.2.0.jar
Url: http://scarab.tigris.org/source/browse/scarab/trunk/www/repository/lucene/jars/lucene-analyzers-2.2.0.jar?view=auto&rev=10486
==============================================================================
Binary file. No diff available.

Added: trunk/www/repository/lucene/jars/lucene-core-2.2.0.jar
Url: http://scarab.tigris.org/source/browse/scarab/trunk/www/repository/lucene/jars/lucene-core-2.2.0.jar?view=auto&rev=10486
==============================================================================
Binary file. No diff available.

Modified: trunk/xdocs/scarab_properties.xml
Url: http://scarab.tigris.org/source/browse/scarab/trunk/xdocs/scarab_properties.xml?view=diff&rev=10486&p1=trunk/xdocs/scarab_properties.xml&p2=trunk/xdocs/scarab_properties.xml&r1=10485&r2=10486
==============================================================================
--- trunk/xdocs/scarab_properties.xml	(original)
+++ trunk/xdocs/scarab_properties.xml	2007-12-04 08:00:13-0800
@@ -1097,6 +1097,25 @@
         <file/>
       </property>
       
+      <property>
+        <name>searchindex.analyzerClass</name>
+        <default>org.tigris.scarab.util.word.PorterStemAnalyzer</default>
+        <comment> 
+          Analyzer class which Lucene uses to index text entered into Scarab.
+          
+          The default Analyzer is optimized for indexing English text.
+          If your Scarab contains mostly non-English text you may want to
+          switch to an Analyzer optimized for your language.
+          Eg. for German you could use: org.apache.lucene.analysis.de.GermanAnalyzer
+          The package org.apache.lucene.analysis contains Analyzers for a lot of
+          other Languages.
+          Of course you are free to write your own Analyzer. 
+        </comment>
+        <type>Runtime</type>
+         <customization modification="optional">advanced</customization>
+        <file/>
+      </property>
+
     </group>
 
     <group name="appserver">
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.