exo-jcr SVN: r196 - in jcr/trunk/component/core/src/test/java: org/exoplatform/services/jcr/impl/core/query/lucene and 1 other directory.
by do-not-reply@jboss.org
Author: skabashnyuk
Date: 2009-10-02 11:39:10 -0400 (Fri, 02 Oct 2009)
New Revision: 196
Removed:
jcr/trunk/component/core/src/test/java/org/exoplatform/services/jcr/impl/core/query/lucene/TestIndexRules.java
jcr/trunk/component/core/src/test/java/org/exoplatform/services/jcr/impl/core/query/lucene/TestNodeIndexer.java
Modified:
jcr/trunk/component/core/src/test/java/conf/standalone/test-jcr-config.xml
jcr/trunk/component/core/src/test/java/org/exoplatform/services/jcr/impl/core/query/lucene/TestErrorLog.java
Log:
EXOJCR-161 : test update
Modified: jcr/trunk/component/core/src/test/java/conf/standalone/test-jcr-config.xml
===================================================================
--- jcr/trunk/component/core/src/test/java/conf/standalone/test-jcr-config.xml 2009-10-02 09:10:30 UTC (rev 195)
+++ jcr/trunk/component/core/src/test/java/conf/standalone/test-jcr-config.xml 2009-10-02 15:39:10 UTC (rev 196)
@@ -298,6 +298,7 @@
<property name="support-highlighting" value="true" />
<property name="indexing-configuration-path" value="../../indexing-configuration.xml" />
<property name="query-class" value="org.exoplatform.services.jcr.impl.core.query.QueryImpl" />
+ <property name="excerptprovider-class" value="org.exoplatform.services.jcr.impl.core.query.lucene.WeightedHTMLExcerpt" />
<property name="spellchecker-class" value="org.exoplatform.services.jcr.impl.core.query.lucene.spell.LuceneSpellChecker$FiveSecondsRefreshInterval" />
</properties>
</query-handler>
Modified: jcr/trunk/component/core/src/test/java/org/exoplatform/services/jcr/impl/core/query/lucene/TestErrorLog.java
===================================================================
--- jcr/trunk/component/core/src/test/java/org/exoplatform/services/jcr/impl/core/query/lucene/TestErrorLog.java 2009-10-02 09:10:30 UTC (rev 195)
+++ jcr/trunk/component/core/src/test/java/org/exoplatform/services/jcr/impl/core/query/lucene/TestErrorLog.java 2009-10-02 15:39:10 UTC (rev 196)
@@ -26,158 +26,137 @@
import java.util.Set;
/**
- * Created by The eXo Platform SAS Author : Sergey Karpenko <sergey.karpenko(a)exoplatform.com.ua>
+ * Created by The eXo Platform SAS Author : Sergey Karpenko
+ * <sergey.karpenko(a)exoplatform.com.ua>
*
* @version $Id: $
*/
-public class TestErrorLog extends BaseQueryTest
-{
- ErrorLog log;
+public class TestErrorLog extends BaseQueryTest {
+ ErrorLog log;
- File file;
+ File file;
- private static final int SIZE = 100;
+ private static final int SIZE = 100;
- public void setUp() throws Exception
- {
- super.setUp();
- file = File.createTempFile("error", "log");
- if (file.exists())
- {
- file.delete();
- }
- }
+ public void setUp() throws Exception {
+ super.setUp();
+ file = File.createTempFile("error", "log");
+ if (file.exists()) {
+ file.delete();
+ }
+ }
- public void tearDown() throws Exception
- {
- super.tearDown();
- log.clear();
- file.delete();
- }
+ public void tearDown() throws Exception {
+ super.tearDown();
+ log.clear();
+ file.delete();
+ }
- public void testConcurrentWrite() throws Exception
- {
+ public void testConcurrentWrite() throws Exception {
- class Loader extends Thread
- {
- private String name;
+ class Loader extends Thread {
+ private String name;
- public Loader(String n)
- {
- name = n;
- }
+ public Loader(String n) {
+ name = n;
+ }
- public void run()
- {
- /*
- * try { for (int i = 0; i < SIZE; i++) { log.append(ErrorLog.ADD,name + i);
- * //System.out.println(name + i); } log.flush(); } catch (Exception e) {
- * System.out.println(e); }
- */
+ public void run() {
+ /*
+ * try { for (int i = 0; i < SIZE; i++) {
+ * log.append(ErrorLog.ADD,name + i); //System.out.println(name
+ * + i); } log.flush(); } catch (Exception e) {
+ * System.out.println(e); }
+ */
- try
- {
- HashSet<String> add = new HashSet<String>();
- HashSet<String> rem = new HashSet<String>();
+ try {
+ HashSet<String> add = new HashSet<String>();
+ HashSet<String> rem = new HashSet<String>();
- for (int j = 0; j < 10; j++)
- {
- add.clear();
- for (int i = 0; i < 10; i++)
- {
- int el = j * 10 + i;
- add.add(name + el);
- }
- log.writeChanges(rem, add);
- }
+ for (int j = 0; j < 10; j++) {
+ add.clear();
+ for (int i = 0; i < 10; i++) {
+ int el = j * 10 + i;
+ add.add(name + el);
+ }
+ log.writeChanges(rem, add);
+ }
- }
- catch (Exception e)
- {
- System.out.println(e);
- }
- }
- }
+ } catch (Exception e) {
+ System.out.println(e);
+ }
+ }
+ }
- log = new ErrorLog(file);
+ log = new ErrorLog(file, SearchIndex.DEFAULT_ERRORLOG_FILE_SIZE);
- Thread one = new Loader("first");
- Thread two = new Loader("second");
- one.start();
- two.start();
- one.join();
- two.join();
+ Thread one = new Loader("first");
+ Thread two = new Loader("second");
+ one.start();
+ two.start();
+ one.join();
+ two.join();
- List<String> list = log.readList();
+ List<String> list = log.readList();
- int lost_first = 0;
- int lost_second = 0;
- for (int i = 0; i < SIZE; i++)
- {
- String firstname = ErrorLog.ADD + " first" + i;
- String secondname = ErrorLog.ADD + " second" + i;
- int ffinded = 0;
- int sfinded = 0;
- for (int j = 0; j < list.size(); j++)
- {
- if (list.get(j).equals(firstname))
- {
- ffinded++;
- }
- if (list.get(j).equals(secondname))
- {
- sfinded++;
- }
- }
- if (ffinded == 0)
- {
- System.out.println(firstname + " NOT FINDED");
- }
- if (ffinded > 1)
- {
- System.out.println(firstname + " DUPLICATED");
- }
- if (sfinded == 0)
- {
- System.out.println(secondname + " NOT FINDED");
- }
- if (sfinded > 1)
- {
- System.out.println(secondname + " DUPLICATED");
- }
- }
+ int lost_first = 0;
+ int lost_second = 0;
+ for (int i = 0; i < SIZE; i++) {
+ String firstname = ErrorLog.ADD + " first" + i;
+ String secondname = ErrorLog.ADD + " second" + i;
+ int ffinded = 0;
+ int sfinded = 0;
+ for (int j = 0; j < list.size(); j++) {
+ if (list.get(j).equals(firstname)) {
+ ffinded++;
+ }
+ if (list.get(j).equals(secondname)) {
+ sfinded++;
+ }
+ }
+ if (ffinded == 0) {
+ System.out.println(firstname + " NOT FINDED");
+ }
+ if (ffinded > 1) {
+ System.out.println(firstname + " DUPLICATED");
+ }
+ if (sfinded == 0) {
+ System.out.println(secondname + " NOT FINDED");
+ }
+ if (sfinded > 1) {
+ System.out.println(secondname + " DUPLICATED");
+ }
+ }
- assertEquals("There is mismatch of expected writed messages count ", 200, list.size());
- assertEquals("First thread has lost apdates", 0, lost_first);
- assertEquals("Second thread has lost apdates", 0, lost_second);
- }
+ assertEquals("There is mismatch of expected writed messages count ",
+ 200, list.size());
+ assertEquals("First thread has lost apdates", 0, lost_first);
+ assertEquals("Second thread has lost apdates", 0, lost_second);
+ }
- public void testExctractNotifyList() throws Exception
- {
- log = new ErrorLog(file);
+ public void testExctractNotifyList() throws Exception {
+ log = new ErrorLog(file, SearchIndex.DEFAULT_ERRORLOG_FILE_SIZE);
- Set<String> removed = new HashSet<String>();
- Set<String> added = new HashSet<String>();
+ Set<String> removed = new HashSet<String>();
+ Set<String> added = new HashSet<String>();
- for (int i = 0; i < 10; i++)
- {
- added.add("uuidadd" + i);
- }
+ for (int i = 0; i < 10; i++) {
+ added.add("uuidadd" + i);
+ }
- for (int i = 0; i < 5; i++)
- {
- removed.add("uuidrem" + i);
- }
+ for (int i = 0; i < 5; i++) {
+ removed.add("uuidrem" + i);
+ }
- log.writeChanges(removed, added);
+ log.writeChanges(removed, added);
- Set<String> rem = new HashSet<String>();
- Set<String> add = new HashSet<String>();
+ Set<String> rem = new HashSet<String>();
+ Set<String> add = new HashSet<String>();
- log.readChanges(rem, add);
+ log.readChanges(rem, add);
- assertTrue(rem.containsAll(removed));
- assertTrue(add.containsAll(added));
- }
+ assertTrue(rem.containsAll(removed));
+ assertTrue(add.containsAll(added));
+ }
}
Deleted: jcr/trunk/component/core/src/test/java/org/exoplatform/services/jcr/impl/core/query/lucene/TestIndexRules.java
===================================================================
--- jcr/trunk/component/core/src/test/java/org/exoplatform/services/jcr/impl/core/query/lucene/TestIndexRules.java 2009-10-02 09:10:30 UTC (rev 195)
+++ jcr/trunk/component/core/src/test/java/org/exoplatform/services/jcr/impl/core/query/lucene/TestIndexRules.java 2009-10-02 15:39:10 UTC (rev 196)
@@ -1,163 +0,0 @@
-/*
- * Copyright (C) 2003-2007 eXo Platform SAS.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Affero General Public License
- * as published by the Free Software Foundation; either version 3
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see<http://www.gnu.org/licenses/>.
- */
-
-package org.exoplatform.services.jcr.impl.core.query.lucene;
-
-import org.apache.lucene.index.IndexReader;
-import org.apache.lucene.index.Term;
-import org.apache.lucene.search.Hits;
-import org.apache.lucene.search.IndexSearcher;
-import org.apache.lucene.search.TermQuery;
-import org.exoplatform.services.jcr.impl.core.query.BaseQueryTest;
-
-import javax.jcr.Node;
-
-/**
- * Created by The eXo Platform SAS Author : Sergey Karpenko <sergey.karpenko(a)exoplatform.com.ua>
- *
- * @version $Id: TestIndexRules.java 11908 2008-03-13 16:00:12Z ksm $
- */
-
-public class TestIndexRules extends BaseQueryTest
-{
-
- public final String fName = "FileName";
-
- private Node rootNode;
-
- public void setUp() throws Exception
- {
- super.setUp();
- rootNode = root.addNode("indrootparent");
- rootNode.setProperty("priority", "low");
- root.save();
- }
-
- /**
- * <index-rule nodeType="nt:unstructured"> <property>DifText</property> </index-rule>
- */
- /*
- * public void testPropAddConfiguration() throws Exception{ //create Node NodeImpl n =
- * (NodeImpl)root.addNode(fName); n.setProperty("DifText","blabla");
- * n.setProperty("OtherProp","gig"); root.save(); //check IndexReader reader =
- * defaultSearchIndex.getIndexReader(false); IndexSearcher is = new IndexSearcher(reader);
- * TermQuery query = new TermQuery(new Term(FieldNames.FULLTEXT, "blabla")); //_PREFIX+fName Hits
- * result = is.search(query); assertEquals(1,result.length()); query = new TermQuery(new
- * Term(FieldNames.FULLTEXT, "gig")); //_PREFIX+fName result = is.search(query);
- * assertEquals(0,result.length()); }
- */
-
- /**
- * <index-rule nodeType="nt:unstructured" boost="2.0" condition="@priority = 'high'">
- * <property>Text</property> </index-rule> <index-rule nodeType="nt:unstructured">
- * <property>DifText</property> </index-rule>
- */
- /*
- * public void testConditionConfiguration() throws Exception{ // create Node NodeImpl n =
- * (NodeImpl)root.addNode(fName); n.setProperty("Text","blabla");
- * n.setProperty("priority","high"); n.setProperty("DifText","second"); root.save(); // check
- * IndexReader reader = defaultSearchIndex.getIndexReader(false); IndexSearcher is = new
- * IndexSearcher(reader); TermQuery query = new TermQuery(new Term(FieldNames.FULLTEXT,
- * "blabla")); Hits result = is.search(query); assertEquals(1,result.length()); query = new
- * TermQuery(new Term(FieldNames.FULLTEXT, "second")); result = is.search(query);
- * assertEquals(0,result.length()); }
- */
-
- /**
- * <index-rule nodeType="nt:unstructured" boost="2.0" condition="@priority = 'high'">
- * <property>Text</property> </index-rule> <index-rule nodeType="nt:unstructured">
- * <property>DifText</property> </index-rule>
- */
- /*
- * public void testConditionConfigurationWrongConditionValue() throws Exception{ Node n =
- * (NodeImpl)root.addNode(fName); n.setProperty("Text","blabla"); n.setProperty("priority","low");
- * n.setProperty("DifText","second"); root.save(); // check IndexReader reader =
- * defaultSearchIndex.getIndexReader(false); IndexSearcher is = new IndexSearcher(reader);
- * TermQuery query = new TermQuery(new Term(FieldNames.FULLTEXT, "blabla")); Hits result =
- * is.search(query); assertEquals(0,result.length()); query = new TermQuery(new
- * Term(FieldNames.FULLTEXT, "second")); result = is.search(query);
- * assertEquals(1,result.length()); }
- */
-
- public void testParentCondition() throws Exception
- {
-
- // create Node
- // assertNotNull(rootNode);
- Node n = rootNode.addNode(fName);
- n.setProperty("Text", "blabla");
- n.setProperty("DifText", "second");
- root.save();
-
- // check
- IndexReader reader = defaultSearchIndex.getIndexReader(false);
- IndexSearcher is = new IndexSearcher(reader);
- TermQuery query = new TermQuery(new Term(FieldNames.FULLTEXT, "blabla"));
- Hits result = is.search(query);
- assertEquals(1, result.length());
-
- query = new TermQuery(new Term(FieldNames.FULLTEXT, "second"));
- result = is.search(query);
- assertEquals(0, result.length());
- }
-
- public void testAncestorCondition() throws Exception
- {
-
- // create Node
- Node rn = rootNode.addNode("hippo");
- Node n = rn.addNode(fName);
- n.setProperty("Text", "blabla");
- n.setProperty("DifText", "second");
- root.save();
-
- // check
- IndexReader reader = defaultSearchIndex.getIndexReader(false);
- IndexSearcher is = new IndexSearcher(reader);
- TermQuery query = new TermQuery(new Term(FieldNames.FULLTEXT, "blabla"));
- Hits result = is.search(query);
- assertEquals(1, result.length());
-
- query = new TermQuery(new Term(FieldNames.FULLTEXT, "second"));
- result = is.search(query);
- assertEquals(0, result.length());
- }
-
- public void testChildCondition() throws Exception
- {
-
- // create Node
- Node n = root.addNode(fName);
- n.setProperty("Text", "blabla");
- n.setProperty("DifText", "second");
- Node cn = n.addNode("indrootchild");
- cn.setProperty("priority", "gg");
- root.save();
-
- // check
- IndexReader reader = defaultSearchIndex.getIndexReader(false);
- IndexSearcher is = new IndexSearcher(reader);
- TermQuery query = new TermQuery(new Term(FieldNames.FULLTEXT, "blabla"));
- Hits result = is.search(query);
- assertEquals(1, result.length());
-
- query = new TermQuery(new Term(FieldNames.FULLTEXT, "second"));
- result = is.search(query);
- assertEquals(0, result.length());
- }
-
-}
Deleted: jcr/trunk/component/core/src/test/java/org/exoplatform/services/jcr/impl/core/query/lucene/TestNodeIndexer.java
===================================================================
--- jcr/trunk/component/core/src/test/java/org/exoplatform/services/jcr/impl/core/query/lucene/TestNodeIndexer.java 2009-10-02 09:10:30 UTC (rev 195)
+++ jcr/trunk/component/core/src/test/java/org/exoplatform/services/jcr/impl/core/query/lucene/TestNodeIndexer.java 2009-10-02 15:39:10 UTC (rev 196)
@@ -1,423 +0,0 @@
-/*
- * Copyright (C) 2003-2007 eXo Platform SAS.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Affero General Public License
- * as published by the Free Software Foundation; either version 3
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see<http://www.gnu.org/licenses/>.
- */
-
-package org.exoplatform.services.jcr.impl.core.query.lucene;
-
-import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
-import org.exoplatform.commons.utils.MimeTypeResolver;
-import org.exoplatform.services.document.DocumentReaderService;
-import org.exoplatform.services.document.impl.DocumentReaderServiceImpl;
-import org.exoplatform.services.jcr.JcrImplBaseTest;
-import org.exoplatform.services.jcr.dataflow.ItemDataConsumer;
-import org.exoplatform.services.jcr.datamodel.NodeData;
-import org.exoplatform.services.jcr.impl.core.NamespaceRegistryImpl;
-import org.exoplatform.services.jcr.impl.core.NodeImpl;
-import org.exoplatform.services.log.ExoLogger;
-import org.exoplatform.services.log.Log;
-
-import java.io.ByteArrayInputStream;
-import java.util.Calendar;
-import java.util.List;
-import java.util.Vector;
-
-import javax.jcr.Node;
-import javax.jcr.PropertyType;
-
-/**
- * Created by The eXo Platform SAS Author : Sergey Karpenko <sergey.karpenko(a)exoplatform.com.ua>
- *
- * @version $Id: TestNodeIndexer.java 11907 2008-03-13 15:36:21Z ksm $
- */
-
-public class TestNodeIndexer extends JcrImplBaseTest
-{
- public static final Log logger = ExoLogger.getLogger(TestNodeIndexer.class);
-
- /**
- * Test node with string valued property.
- * <p>
- * In this case there are:
- * <p>
- * - node "test"
- * <p>
- * - property "jcr:primaryType" val "nt:ustructured" string
- * <p>
- * - property "jcr:prop" val "prop value" string
- * <p>
- * <p>
- * Expected lucene document structure. Fields:
- * <p>
- * _:UUID uuid of node;
- * <p>
- * _:PARENT uuid of parent node _:LABEL name of the node "test"
- * <p>
- * _:PROPERTIES "jcr:primaryType"+'\uFFFF'+"nt:unstructured" _:PROPERTIES
- * "jcr:prop"+'\uFFFF'+"prop value"
- * <p>
- * _:FULLTEXT "prop value"
- * <p>
- * jcr:FULL:prop "prop value"
- * <p>
- *
- *
- * @throws Exception
- */
- @SuppressWarnings("unchecked")
- public void testCreateDocument_String() throws Exception
- {
-
- Node node = this.root.addNode("test");
- node.setProperty("jcr:prop", "prop value");
- root.save();
-
- ItemDataConsumer manager = this.session.getTransientNodesManager();
-
- node = (Node)this.session.getItem("/test");
-
- NodeData data = (NodeData)((NodeImpl)node).getData();
- assertNotNull(data);
-
- DocumentReaderService extractor =
- (DocumentReaderService)container.getComponentInstanceOfType(DocumentReaderServiceImpl.class);
- NodeIndexer indexer =
- new NodeIndexer(data, manager, new NSRegistryBasedNamespaceMappings((NamespaceRegistryImpl)this.repository
- .getNamespaceRegistry()), extractor);
-
- Document doc = indexer.createDoc();
-
- List<Field> list = doc.getFields();
-
- // _:UUID
- List<Field> uuid = this.findField(list, FieldNames.UUID);
- assertNotNull(uuid);
- assertEquals(1, uuid.size());
- assertEquals(data.getIdentifier(), uuid.get(0).stringValue());
-
- // _:PARENT
- List<Field> parent = this.findField(list, FieldNames.PARENT);
- assertNotNull(parent);
- assertEquals(1, parent.size());
- assertEquals(data.getParentIdentifier(), parent.get(0).stringValue());
-
- // _:LABEL
- List<Field> label = this.findField(list, FieldNames.LABEL);
- assertNotNull(label);
- assertEquals(1, label.size());
- assertEquals(node.getName(), label.get(0).stringValue());
-
- // _:PROPERTIES jcr:primaryType
- List<Field> props = this.findField(list, FieldNames.PROPERTIES);
- assertNotNull(props);
- assertEquals(2, props.size());
-
- // :PROPERTIES jcr:primaryType "jcr:prop" + '\uFFFF' + "prop value"
- List<Field> prop1 = this.findField(list, FieldNames.PROPERTIES, "jcr:prop" + '[' + "prop value");
- assertNotNull(prop1);
- assertEquals(1, prop1.size());
-
- // :PROPERTIES jcr:primaryType "jcr:prop" + '\uFFFF' + "prop value"
- List<Field> prop2 = this.findField(list, FieldNames.PROPERTIES, "jcr:primaryType" + '[' + "nt:unstructured");
- assertNotNull(prop2);
- assertEquals(1, prop2.size());
-
- // _:FULLTEXT
- List<Field> full = this.findField(list, FieldNames.FULLTEXT);
- assertNotNull(full);
- assertEquals(1, full.size());
- assertEquals(node.getProperty("jcr:prop").getString(), full.get(0).stringValue());
-
- // jcr:FULL:prop "prop","value"
- List<Field> prefixed = this.findField(list, "jcr:FULL:prop");
- assertNotNull(prefixed);
- assertEquals(1, prefixed.size());
- assertEquals(node.getProperty("jcr:prop").getString(), prefixed.get(0).stringValue());
-
- // Check sum - there must be 6 fields
- assertEquals(7, list.size());
- }
-
- /**
- * Test root node indexing;
- * <p>
- * In this case there are:
- * <p>
- * - root node
- * <p>
- * Expected lucene document structure. Fields:
- * <p>
- * _:UUID uuid of root node;
- * <p>
- * _:PARENT "" _:LABEL name ""
- *
- * @throws Exception
- */
- @SuppressWarnings("unchecked")
- public void testCreateDocumentRootNode() throws Exception
- {
-
- ItemDataConsumer manager = this.session.getTransientNodesManager();
-
- // ((NodeImpl)node).getData();
-
- NodeData data = (NodeData)((NodeImpl)root).getData();
- assertNotNull(data);
-
- DocumentReaderService extractor =
- (DocumentReaderService)container.getComponentInstanceOfType(DocumentReaderServiceImpl.class);
- NodeIndexer indexer =
- new NodeIndexer(data, manager, new NSRegistryBasedNamespaceMappings((NamespaceRegistryImpl)this.repository
- .getNamespaceRegistry()), extractor);
-
- Document doc = indexer.createDoc();
-
- List<Field> list = doc.getFields();
-
- // _:UUID
- List<Field> uuid = this.findField(list, FieldNames.UUID);
- assertNotNull(uuid);
- assertEquals(1, uuid.size());
- assertEquals(data.getIdentifier(), uuid.get(0).stringValue());
-
- // _:PARENT
- List<Field> parent = this.findField(list, FieldNames.PARENT);
- assertNotNull(parent);
- assertEquals(1, parent.size());
- assertEquals("", parent.get(0).stringValue());
-
- // _:LABEL
- List<Field> label = this.findField(list, FieldNames.LABEL);
- assertNotNull(label);
- assertEquals(1, label.size());
- assertEquals("", label.get(0).stringValue());
- }
-
- /**
- * Test of indexing Binary value
- * <p>
- * In this case there are:
- * <p>
- * - node "jcr:content"
- * <p>
- * - property "jcr:primaryType" val "nt:resource" name
- * <p>
- * - property "jcr:lastModified" calendar
- * <p>
- * - property "jcr:uuid" string
- * <p>
- * - property "jcr:mimetype" "text/plain" string
- * <p>
- * - property "jcr:data" "binary value" binary
- * <p>
- * Expected lucene document structure. Fields:
- * <p>
- * _:UUID uuid of node;
- * <p>
- * _:PARENT uuid of parent node _:LABEL name of the node "test"
- * <p>
- * _:PROPERTIES "jcr:primaryType"+'\uFFFF'+"nt:resource"
- * <p>
- * _:PROPERTIES "jcr:lastModified"+'\uFFFF'+currentTtimeString
- * <p>
- * _:PROPERTIES "jcr:uuid"+'\uFFFF'+ uuid
- * <p>
- * jcr:FULL:uuid uuid
- * <p>
- * _:PROPERTIES "jcr:mimetype"+'\uFFFF'+"text/plain"
- * <p>
- * _:FULLTEXT "text/plain"
- * <p>
- * _:FULLTEXT "binary value"
- * <p>
- *
- *
- *
- * @throws Exception
- */
- @SuppressWarnings("unchecked")
- public void testCreateDocument_Binary() throws Exception
- {
- Node node = root.addNode("jcr:content", "nt:resource");
-
- MimeTypeResolver mimetypeResolver = new MimeTypeResolver();
- mimetypeResolver.setDefaultMimeType("text/plain");// "application/zip");
- String mimeType = mimetypeResolver.getMimeType("text/plain");
-
- node.setProperty("jcr:mimeType", mimeType);
- node.setProperty("jcr:lastModified", Calendar.getInstance());
- node.setProperty("jcr:data", new ByteArrayInputStream("binary value".getBytes()));
-
- root.save();
-
- ItemDataConsumer manager = this.session.getTransientNodesManager();
-
- NodeData data = (NodeData)((NodeImpl)node).getData();
- assertNotNull(data);
-
- DocumentReaderService extractor =
- (DocumentReaderService)container.getComponentInstanceOfType(DocumentReaderServiceImpl.class);
- NodeIndexer indexer =
- new NodeIndexer(data, manager, new NSRegistryBasedNamespaceMappings((NamespaceRegistryImpl)this.repository
- .getNamespaceRegistry()), extractor);
-
- Document doc = indexer.createDoc();
-
- List<Field> list = doc.getFields();
-
- // Check sum - there must be 6 fields
- assertEquals(10, list.size());
-
- // _:UUID
- List<Field> uuid = this.findField(list, FieldNames.UUID);
- assertNotNull(uuid);
- assertEquals(1, uuid.size());
- assertEquals(data.getIdentifier(), uuid.get(0).stringValue());
-
- // _:PARENT
- List<Field> parent = this.findField(list, FieldNames.PARENT);
- assertNotNull(parent);
- assertEquals(1, parent.size());
- assertEquals(data.getParentIdentifier(), parent.get(0).stringValue());
-
- // _:LABEL
- List<Field> label = this.findField(list, FieldNames.LABEL);
- assertNotNull(label);
- assertEquals(1, label.size());
- assertEquals(node.getName(), label.get(0).stringValue());
-
- }
-
- /**
- * Test of indexing Binary value
- * <p>
- * In this case there are:
- * <p>
- * - node "jcr:content"
- * <p>
- * - property "jcr:primaryType" val "nt:unstructured" name
- * <p>
- * - property "pathprop" "/wooo" path
- * <p>
- * Expected lucene document structure. Fields:
- * <p>
- * _:UUID uuid of node;
- * <p>
- * _:PARENT uuid of parent node _:LABEL name of the node "test"
- * <p>
- * _:PROPERTIES "jcr:primaryType"+'\uFFFF'+"nt:unstructured"
- * <p>
- * _:PROPERTIES "pathprop"+'\uFFFF'+"/wooo"
- * <p>
- *
- * @throws Exception
- */
- @SuppressWarnings("unchecked")
- public void testCreateDocument_Path() throws Exception
- {
- Node node = root.addNode("test_path");
-
- node.setProperty("pathprop", "/wooo", PropertyType.PATH);
-
- root.save();
-
- ItemDataConsumer manager = this.session.getTransientNodesManager();
-
- NodeData data = (NodeData)((NodeImpl)node).getData();
- assertNotNull(data);
-
- DocumentReaderService extractor =
- (DocumentReaderService)container.getComponentInstanceOfType(DocumentReaderServiceImpl.class);
- NodeIndexer indexer =
- new NodeIndexer(data, manager, new NSRegistryBasedNamespaceMappings((NamespaceRegistryImpl)this.repository
- .getNamespaceRegistry()), extractor);
-
- Document doc = indexer.createDoc();
-
- List<Field> list = doc.getFields();
-
- // Check sum - there must be 6 fields
- assertEquals(5, list.size());
-
- // _:UUID
- List<Field> uuid = this.findField(list, FieldNames.UUID);
- assertNotNull(uuid);
- assertEquals(1, uuid.size());
- assertEquals(data.getIdentifier(), uuid.get(0).stringValue());
-
- // _:PARENT
- List<Field> parent = this.findField(list, FieldNames.PARENT);
- assertNotNull(parent);
- assertEquals(1, parent.size());
- assertEquals(data.getParentIdentifier(), parent.get(0).stringValue());
-
- // _:LABEL
- List<Field> label = this.findField(list, FieldNames.LABEL);
- assertNotNull(label);
- assertEquals(1, label.size());
- assertEquals(node.getName(), label.get(0).stringValue());
-
- // _:PROPERTIES
- List<Field> props = this.findField(list, FieldNames.PROPERTIES);
- assertNotNull(props);
- assertEquals(2, props.size());
-
- // :PROPERTIES jcr:primaryType "pathprop" + '\uFFFF' + "/wooo"
- List<Field> prop1 = this.findField(list, FieldNames.PROPERTIES, "pathprop" + '[' + "/wooo");
- assertNotNull(prop1);
- assertEquals(1, prop1.size());
-
- // :PROPERTIES jcr:primaryType "jcr:primaryType" + '\uFFFF' + "jcr:primaryType" + '\uFFFF' +
- // "nt:unstructured"
- List<Field> prop2 = this.findField(list, FieldNames.PROPERTIES, "jcr:primaryType" + '[' + "nt:unstructured");
- assertNotNull(prop2);
- assertEquals(1, prop2.size());
-
- }
-
- /**
- * @return Field or null if is not finded
- */
- public List<Field> findField(List<Field> list, String fieldName)
- {
- List<Field> out = new Vector<Field>();
- for (int i = 0; i < list.size(); i++)
- {
- if (list.get(i).name().equalsIgnoreCase(fieldName))
- out.add(list.get(i));
- }
- return (out.isEmpty()) ? null : out;
- }
-
- /**
- * Find Field from list, named as fieldName, and valued as fieldStringValue
- *
- * @return Field or null if is not finded
- */
- public List<Field> findField(List<Field> list, String fieldName, String fieldStringValue)
- {
- List<Field> out = new Vector<Field>();
- for (int i = 0; i < list.size(); i++)
- {
- if ((list.get(i).name().equalsIgnoreCase(fieldName)) && (list.get(i).stringValue() != null)
- && (list.get(i).stringValue().equals(fieldStringValue)))
- {
- out.add(list.get(i));
- }
- }
- return (out.isEmpty()) ? null : out;
- }
-}
14 years, 7 months
exo-jcr SVN: r195 - jcr/trunk/component/core.
by do-not-reply@jboss.org
Author: skabashnyuk
Date: 2009-10-02 05:10:30 -0400 (Fri, 02 Oct 2009)
New Revision: 195
Modified:
jcr/trunk/component/core/pom.xml
Log:
EXOJCR-161 : tck test cleanup
Modified: jcr/trunk/component/core/pom.xml
===================================================================
--- jcr/trunk/component/core/pom.xml 2009-10-02 08:25:49 UTC (rev 194)
+++ jcr/trunk/component/core/pom.xml 2009-10-02 09:10:30 UTC (rev 195)
@@ -521,57 +521,20 @@
<property>
<name>known.issues</name>
<value>
- org.apache.jackrabbit.test.api.nodetype.PropertyDefTest#testIsRequiredType
- org.apache.jackrabbit.test.api.DocumentViewImportTest#testSessionImportXml
- org.apache.jackrabbit.test.api.DocumentViewImportTest#testWorkspaceImportXml
- org.apache.jackrabbit.test.api.DocumentViewImportTest#testWorkspaceGetImportContentHandler
- org.apache.jackrabbit.test.api.DocumentViewImportTest#testSessionGetImportContentHandler
- org.apache.jackrabbit.test.api.SetPropertyConstraintViolationExceptionTest#testBooleanProperty
- org.apache.jackrabbit.test.api.SetValueConstraintViolationExceptionTest#testMultipleBooleanProperty
org.apache.jackrabbit.test.api.SetValueConstraintViolationExceptionTest#testBooleanProperty
- org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreName
- org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreOrder
- org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreOrder2
- org.apache.jackrabbit.test.api.NamespaceRegistryTest#testRegisterNamespace
- org.apache.jackrabbit.test.api.SetValueConstraintViolationExceptionTest#testBooleanProperty
org.apache.jackrabbit.test.api.SetValueConstraintViolationExceptionTest#testMultipleBooleanProperty
- org.apache.jackrabbit.test.api.SetPropertyConstraintViolationExceptionTest#testBooleanProperty
- org.apache.jackrabbit.test.api.nodetype.PropertyDefTest#testIsRequiredType
- org.apache.jackrabbit.test.api.nodetype.PredefinedNodeTypeTest#testVersionable
- org.apache.jackrabbit.test.api.version.RestoreTest#testVersion
org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreName
org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreOrder
org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreOrder2
- org.apache.jackrabbit.test.api.NamespaceRegistryTest#testRegisterNamespace
- org.apache.jackrabbit.test.api.SetValueConstraintViolationExceptionTest#testBooleanProperty
- org.apache.jackrabbit.test.api.SetValueConstraintViolationExceptionTest#testMultipleBooleanProperty
- org.apache.jackrabbit.test.api.SetPropertyConstraintViolationExceptionTest#testBooleanProperty
org.apache.jackrabbit.test.api.nodetype.PropertyDefTest#testIsRequiredType
- org.apache.jackrabbit.test.api.nodetype.PredefinedNodeTypeTest#testVersionable
- org.apache.jackrabbit.test.api.version.RestoreTest#testVersion
- org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreName
- org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreOrder
- org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreOrder2
- org.apache.jackrabbit.test.api.NamespaceRegistryTest#testRegisterNamespace
- org.apache.jackrabbit.test.api.nodetype.PredefinedNodeTypeTest#testVersion
- </value>
- </property>
- <!-- property>
- <name>known.issues</name>
- <value>
- org.apache.jackrabbit.test.api.nodetype.PropertyDefTest#testIsRequiredType
- org.apache.jackrabbit.test.api.DocumentViewImportTest#testSessionImportXml
- org.apache.jackrabbit.test.api.DocumentViewImportTest#testWorkspaceImportXml
- org.apache.jackrabbit.test.api.DocumentViewImportTest#testWorkspaceGetImportContentHandler
- org.apache.jackrabbit.test.api.DocumentViewImportTest#testSessionGetImportContentHandler
org.apache.jackrabbit.test.api.SetPropertyConstraintViolationExceptionTest#testBooleanProperty
- org.apache.jackrabbit.test.api.SetValueConstraintViolationExceptionTest#testMultipleBooleanProperty
- org.apache.jackrabbit.test.api.SetValueConstraintViolationExceptionTest#testBooleanProperty
- org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreName
- org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreOrder
- org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreOrder2
+ org.apache.jackrabbit.test.api.nodetype.PredefinedNodeTypeTest#testShareable
+ org.apache.jackrabbit.test.api.nodetype.PredefinedNodeTypeTest#testSimpleVersionable
+ org.apache.jackrabbit.test.api.nodetype.PredefinedNodeTypeTest#testActivity
+ org.apache.jackrabbit.test.api.nodetype.PredefinedNodeTypeTest#testConfiguration
+ org.apache.jackrabbit.test.api.NamespaceRegistryTest#testRegisterNamespace
</value>
- </property -->
+ </property>
</systemProperties>
<includes>
<include>**/api/*Test.java</include>
14 years, 7 months
exo-jcr SVN: r194 - in jcr/trunk/component/core/src: main/java/org/exoplatform/services/jcr/impl/core/query/lucene and 2 other directories.
by do-not-reply@jboss.org
Author: skabashnyuk
Date: 2009-10-02 04:25:49 -0400 (Fri, 02 Oct 2009)
New Revision: 194
Added:
jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/IndexingTree.java
jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/SearchIndexConfigurationHelper.java
Modified:
jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/QueryHandlerContext.java
jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/SearchManager.java
jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/SystemSearchManager.java
jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/MultiIndex.java
jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SearchIndex.java
jcr/trunk/component/core/src/test/java/org/exoplatform/services/jcr/api/core/query/TestAll.java
jcr/trunk/component/core/src/test/java/org/exoplatform/services/jcr/api/core/query/lucene/directory/DirectoryManagerTest.java
Log:
EXOJCR-161 : Index startup update
Added: jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/IndexingTree.java
===================================================================
--- jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/IndexingTree.java (rev 0)
+++ jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/IndexingTree.java 2009-10-02 08:25:49 UTC (rev 194)
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2009 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.exoplatform.services.jcr.impl.core.query;
+
+import org.exoplatform.services.jcr.dataflow.ItemState;
+import org.exoplatform.services.jcr.datamodel.ItemData;
+import org.exoplatform.services.jcr.datamodel.NodeData;
+import org.exoplatform.services.jcr.datamodel.QPath;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:Sergey.Kabashnyuk@exoplatform.org">Sergey
+ * Kabashnyuk</a>
+ * @version $Id: exo-jboss-codetemplates.xml 34360 2009-07-22 23:58:59Z ksm $
+ *
+ */
+public class IndexingTree {
+ private final QPath indexingRootQpath;
+ private final NodeData indexingRoot;
+
+ private final List<QPath> excludedPaths;
+
+ /**
+ * @param indexingRoot
+ * @param excludedPaths
+ */
+ public IndexingTree(NodeData indexingRoot, List<QPath> excludedPaths) {
+ super();
+ this.indexingRoot = indexingRoot;
+ this.indexingRootQpath = indexingRoot.getQPath();
+ this.excludedPaths = excludedPaths;
+ }
+
+ /**
+ * @param indexingRoot
+ * @param excludedPaths
+ */
+ public IndexingTree(NodeData indexingRoot) {
+ super();
+ this.indexingRoot = indexingRoot;
+ this.indexingRootQpath = indexingRoot.getQPath();
+ this.excludedPaths = new ArrayList<QPath>();
+ }
+
+ /**
+ * @return the excludedPaths
+ */
+ public List<QPath> getExcludedPaths() {
+ return excludedPaths;
+ }
+
+ /**
+ * @return the indexingRoot
+ */
+ public NodeData getIndexingRoot() {
+ return indexingRoot;
+ }
+
+ /**
+ * Checks if the given event should be excluded based on the
+ * {@link #excludePath} setting.
+ *
+ * @param event
+ * observation event
+ * @return <code>true</code> if the event should be excluded,
+ * <code>false</code> otherwise
+ */
+ public boolean isExcluded(ItemState event) {
+
+ for (QPath excludedPath : excludedPaths) {
+ if (event.getData().getQPath().isDescendantOf(excludedPath)
+ || event.getData().getQPath().equals(excludedPath))
+ return true;
+ }
+
+ return !event.getData().getQPath().isDescendantOf(indexingRootQpath)
+ && !event.getData().getQPath().equals(indexingRootQpath);
+ }
+
+ /**
+ * Checks if the given event should be excluded based on the
+ * {@link #excludePath} setting.
+ *
+ * @param event
+ * observation event
+ * @return <code>true</code> if the event should be excluded,
+ * <code>false</code> otherwise
+ */
+ public boolean isExcluded(ItemData eventData) {
+
+ for (QPath excludedPath : excludedPaths) {
+ if (eventData.getQPath().isDescendantOf(excludedPath)
+ || eventData.getQPath().equals(excludedPath))
+ return true;
+ }
+
+ return !eventData.getQPath().isDescendantOf(indexingRootQpath)
+ && !eventData.getQPath().equals(indexingRootQpath);
+ }
+}
Property changes on: jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/IndexingTree.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/QueryHandlerContext.java
===================================================================
--- jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/QueryHandlerContext.java 2009-10-01 15:37:53 UTC (rev 193)
+++ jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/QueryHandlerContext.java 2009-10-02 08:25:49 UTC (rev 194)
@@ -27,152 +27,163 @@
* stable. This class provides access to the environment where the query handler
* is running in.
*/
-public class QueryHandlerContext
-{
- /**
- * The persistent <code>ItemStateManager</code>
- */
- private final ItemDataConsumer stateMgr;
+public class QueryHandlerContext {
+ /**
+ * The persistent <code>ItemStateManager</code>
+ */
+ private final ItemDataConsumer stateMgr;
- /**
- * The node type registry of the repository
- */
- private final NodeTypeDataManager nodeTypeDataManager;
+ /**
+ * The node type registry of the repository
+ */
+ private final NodeTypeDataManager nodeTypeDataManager;
- /**
- * The namespace registry of the repository.
- */
- private final NamespaceRegistryImpl nsRegistry;
+ /**
+ * The namespace registry of the repository.
+ */
+ private final NamespaceRegistryImpl nsRegistry;
- /**
- * The id of the root node.
- */
- private final String rootIdentifer;
+ /**
+ * The id of the root node.
+ */
+ private final IndexingTree indexingTree;
- /**
- * PropertyType registry to look up the type of a property with a given name.
- */
- private final PropertyTypeRegistry propRegistry;
+ /**
+ * PropertyType registry to look up the type of a property with a given
+ * name.
+ */
+ private final PropertyTypeRegistry propRegistry;
- /**
- * The query handler for the jcr:system tree
- */
- private final QueryHandler parentHandler;
+ /**
+ * The query handler for the jcr:system tree
+ */
+ private final QueryHandler parentHandler;
- /**
- * Text extractor for extracting text content of binary properties.
- */
- private final DocumentReaderService extractor;
+ /**
+ * Text extractor for extracting text content of binary properties.
+ */
+ private final DocumentReaderService extractor;
- private final String indexDirectory;
+ private final String indexDirectory;
- /**
- * Creates a new context instance.
- *
- * @param fs a this <code>QueryHandler</code> may use to store its index. If
- * no <code>FileSystem</code> has been configured <code>fs</code> is
- * <code>null</code>.
- * @param stateMgr provides persistent item states.
- * @param rootId the id of the root node.
- * @param ntRegistry the node type registry.
- * @param nsRegistry the namespace registry.
- * @param parentHandler the parent query handler or <code>null</code> it there
- * is no parent handler.
- * @param excludedNodeId id of the node that should be excluded from indexing.
- * Any descendant of that node is also excluded from indexing.
- */
- public QueryHandlerContext(ItemDataConsumer stateMgr, String rootIdentifer, NodeTypeDataManager nodeTypeDataManager,
- NamespaceRegistryImpl nsRegistry, QueryHandler parentHandler, String indexDirectory,
- DocumentReaderService extractor)
- {
- this.stateMgr = stateMgr;
- this.rootIdentifer = rootIdentifer;
- this.nodeTypeDataManager = nodeTypeDataManager;
- this.nsRegistry = nsRegistry;
- this.indexDirectory = indexDirectory;
- this.extractor = extractor;
- this.propRegistry = new PropertyTypeRegistry(nodeTypeDataManager);
- this.parentHandler = parentHandler;
- ((NodeTypeDataManagerImpl)this.nodeTypeDataManager).addListener(propRegistry);
- }
+ private final boolean createInitialIndex;
- /**
- * Returns the persistent {@link ItemStateManager} of the workspace this
- * <code>QueryHandler</code> is based on.
- *
- * @return the persistent <code>ItemStateManager</code> of the current
- * workspace.
- */
- public ItemDataConsumer getItemStateManager()
- {
- return stateMgr;
- }
+ /**
+ * Creates a new context instance.
+ *
+ * @param fs
+ * a this <code>QueryHandler</code> may use to store its index.
+ * If no <code>FileSystem</code> has been configured
+ * <code>fs</code> is <code>null</code>.
+ * @param stateMgr
+ * provides persistent item states.
+ * @param rootId
+ * the id of the root node.
+ * @param ntRegistry
+ * the node type registry.
+ * @param nsRegistry
+ * the namespace registry.
+ * @param parentHandler
+ * the parent query handler or <code>null</code> it there is no
+ * parent handler.
+ * @param excludedNodeId
+ * id of the node that should be excluded from indexing. Any
+ * descendant of that node is also excluded from indexing.
+ */
+ public QueryHandlerContext(ItemDataConsumer stateMgr,
+ IndexingTree indexingTree, NodeTypeDataManager nodeTypeDataManager,
+ NamespaceRegistryImpl nsRegistry, QueryHandler parentHandler,
+ String indexDirectory, DocumentReaderService extractor,
+ boolean createInitialIndex) {
+ this.stateMgr = stateMgr;
+ this.indexingTree = indexingTree;
+ this.nodeTypeDataManager = nodeTypeDataManager;
+ this.nsRegistry = nsRegistry;
+ this.indexDirectory = indexDirectory;
+ this.extractor = extractor;
+ this.createInitialIndex = createInitialIndex;
+ this.propRegistry = new PropertyTypeRegistry(nodeTypeDataManager);
+ this.parentHandler = parentHandler;
+ ((NodeTypeDataManagerImpl) this.nodeTypeDataManager)
+ .addListener(propRegistry);
+ }
- /**
- * Returns the id of the root node.
- *
- * @return the idof the root node.
- */
- public String getRootNodeIdentifer()
- {
- return rootIdentifer;
- }
+ /**
+ * @return the createInitialIndex
+ */
+ public boolean isCreateInitialIndex() {
+ return createInitialIndex;
+ }
- /**
- * Returns the PropertyTypeRegistry for this repository.
- *
- * @return the PropertyTypeRegistry for this repository.
- */
- public PropertyTypeRegistry getPropertyTypeRegistry()
- {
- return propRegistry;
- }
+ /**
+ * Returns the persistent {@link ItemStateManager} of the workspace this
+ * <code>QueryHandler</code> is based on.
+ *
+ * @return the persistent <code>ItemStateManager</code> of the current
+ * workspace.
+ */
+ public ItemDataConsumer getItemStateManager() {
+ return stateMgr;
+ }
- /**
- * Returns the NodeTypeRegistry for this repository.
- *
- * @return the NodeTypeRegistry for this repository.
- */
- public NodeTypeDataManager getNodeTypeDataManager()
- {
- return nodeTypeDataManager;
- }
+ /**
+ * Returns the id of the root node.
+ *
+ * @return the idof the root node.
+ */
+ public IndexingTree getIndexingTree() {
+ return indexingTree;
+ }
- /**
- * Returns the NamespaceRegistryImpl for this repository.
- *
- * @return the NamespaceRegistryImpl for this repository.
- */
- public NamespaceRegistryImpl getNamespaceRegistry()
- {
- return nsRegistry;
- }
+ /**
+ * Returns the PropertyTypeRegistry for this repository.
+ *
+ * @return the PropertyTypeRegistry for this repository.
+ */
+ public PropertyTypeRegistry getPropertyTypeRegistry() {
+ return propRegistry;
+ }
- /**
- * Returns the parent query handler.
- *
- * @return the parent query handler.
- */
- public QueryHandler getParentHandler()
- {
- return parentHandler;
- }
+ /**
+ * Returns the NodeTypeRegistry for this repository.
+ *
+ * @return the NodeTypeRegistry for this repository.
+ */
+ public NodeTypeDataManager getNodeTypeDataManager() {
+ return nodeTypeDataManager;
+ }
- /**
- * Destroys this context and releases resources.
- */
- public void destroy()
- {
- ((NodeTypeDataManagerImpl)this.nodeTypeDataManager).removeListener(propRegistry);
- }
+ /**
+ * Returns the NamespaceRegistryImpl for this repository.
+ *
+ * @return the NamespaceRegistryImpl for this repository.
+ */
+ public NamespaceRegistryImpl getNamespaceRegistry() {
+ return nsRegistry;
+ }
- public DocumentReaderService getExtractor()
- {
- return extractor;
- }
+ /**
+ * Returns the parent query handler.
+ *
+ * @return the parent query handler.
+ */
+ public QueryHandler getParentHandler() {
+ return parentHandler;
+ }
- public String getIndexDirectory()
- {
- return indexDirectory;
- }
+ /**
+ * Destroys this context and releases resources.
+ */
+ public void destroy() {
+ ((NodeTypeDataManagerImpl) this.nodeTypeDataManager)
+ .removeListener(propRegistry);
+ }
+
+ public DocumentReaderService getExtractor() {
+ return extractor;
+ }
+
+ public String getIndexDirectory() {
+ return indexDirectory;
+ }
}
Added: jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/SearchIndexConfigurationHelper.java
===================================================================
--- jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/SearchIndexConfigurationHelper.java (rev 0)
+++ jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/SearchIndexConfigurationHelper.java 2009-10-02 08:25:49 UTC (rev 194)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2009 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.exoplatform.services.jcr.impl.core.query;
+
+import org.exoplatform.services.jcr.config.QueryHandlerEntry;
+import org.exoplatform.services.jcr.config.RepositoryConfigurationException;
+import org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex;
+
+import java.io.IOException;
+
+/**
+ * @author <a href="mailto:Sergey.Kabashnyuk@exoplatform.org">Sergey
+ * Kabashnyuk</a>
+ * @version $Id: exo-jboss-codetemplates.xml 34360 2009-07-22 23:58:59Z ksm $
+ *
+ */
+public class SearchIndexConfigurationHelper {
+
+ private final SearchIndex searchIndex;
+
+ /**
+ * @param searchIndex
+ */
+ public SearchIndexConfigurationHelper(SearchIndex searchIndex) {
+ super();
+ this.searchIndex = searchIndex;
+ }
+
+ public void init(QueryHandlerEntry queryHandlerEntry) throws IOException,
+ RepositoryConfigurationException {
+ // Path will be set using queryHandelContext
+
+ }
+}
Property changes on: jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/SearchIndexConfigurationHelper.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/SearchManager.java
===================================================================
--- jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/SearchManager.java 2009-10-01 15:37:53 UTC (rev 193)
+++ jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/SearchManager.java 2009-10-02 08:25:49 UTC (rev 194)
@@ -59,525 +59,488 @@
/**
* Acts as a global entry point to execute queries and index nodes.
*/
-public class SearchManager implements Startable, MandatoryItemsPersistenceListener
-{
+public class SearchManager implements Startable,
+ MandatoryItemsPersistenceListener {
- /**
- * Logger instance for this class
- */
- private static final Log log = ExoLogger.getLogger(SearchManager.class);
+ /**
+ * Logger instance for this class
+ */
+ private static final Log log = ExoLogger.getLogger(SearchManager.class);
- protected final QueryHandlerEntryWrapper config;
+ protected final QueryHandlerEntryWrapper config;
- /**
- * Text extractor for extracting text content of binary properties.
- */
- protected final DocumentReaderService extractor;
+ /**
+ * Text extractor for extracting text content of binary properties.
+ */
+ protected final DocumentReaderService extractor;
- /**
- * QueryHandler where query execution is delegated to
- */
- protected QueryHandler handler;
+ /**
+ * QueryHandler where query execution is delegated to
+ */
+ protected QueryHandler handler;
- /**
- * The shared item state manager instance for the workspace.
- */
- protected final ItemDataConsumer itemMgr;
+ /**
+ * The shared item state manager instance for the workspace.
+ */
+ protected final ItemDataConsumer itemMgr;
- /**
- * The namespace registry of the repository.
- */
- protected final NamespaceRegistryImpl nsReg;
+ /**
+ * The namespace registry of the repository.
+ */
+ protected final NamespaceRegistryImpl nsReg;
- /**
- * The node type registry.
- */
- protected final NodeTypeDataManager nodeTypeDataManager;
+ /**
+ * The node type registry.
+ */
+ protected final NodeTypeDataManager nodeTypeDataManager;
- /**
- * QueryHandler of the parent search manager or <code>null</code> if there is
- * none.
- */
- protected final SearchManager parentSearchManager;
+ /**
+ * QueryHandler of the parent search manager or <code>null</code> if there
+ * is none.
+ */
+ protected final SearchManager parentSearchManager;
- protected QPath indexingRoot;
+ // protected QPath indexingRoot;
+ //
+ // protected List<QPath> excludedPaths = new ArrayList<QPath>();
- protected List<QPath> excludedPaths = new ArrayList<QPath>();
+ protected IndexingTree indexingTree;
- private final ConfigurationManager cfm;
+ private final ConfigurationManager cfm;
- /**
- * Creates a new <code>SearchManager</code>.
- *
- * @param config the search configuration.
- * @param nsReg the namespace registry.
- * @param ntReg the node type registry.
- * @param itemMgr the shared item state manager.
- * @param rootNodeId the id of the root node.
- * @param parentMgr the parent search manager or <code>null</code> if there is
- * no parent search manager.
- * @param excludedNodeId id of the node that should be excluded from indexing.
- * Any descendant of that node will also be excluded from indexing.
- * @throws RepositoryException if the search manager cannot be initialized
- * @throws RepositoryConfigurationException
- */
- public SearchManager(QueryHandlerEntry config, NamespaceRegistryImpl nsReg, NodeTypeDataManager ntReg,
- WorkspacePersistentDataManager itemMgr, SystemSearchManagerHolder parentSearchManager,
- DocumentReaderService extractor, ConfigurationManager cfm) throws RepositoryException,
- RepositoryConfigurationException
- {
+ /**
+ * Creates a new <code>SearchManager</code>.
+ *
+ * @param config
+ * the search configuration.
+ * @param nsReg
+ * the namespace registry.
+ * @param ntReg
+ * the node type registry.
+ * @param itemMgr
+ * the shared item state manager.
+ * @param rootNodeId
+ * the id of the root node.
+ * @param parentMgr
+ * the parent search manager or <code>null</code> if there is no
+ * parent search manager.
+ * @param excludedNodeId
+ * id of the node that should be excluded from indexing. Any
+ * descendant of that node will also be excluded from indexing.
+ * @throws RepositoryException
+ * if the search manager cannot be initialized
+ * @throws RepositoryConfigurationException
+ */
+ public SearchManager(QueryHandlerEntry config, NamespaceRegistryImpl nsReg,
+ NodeTypeDataManager ntReg, WorkspacePersistentDataManager itemMgr,
+ SystemSearchManagerHolder parentSearchManager,
+ DocumentReaderService extractor, ConfigurationManager cfm)
+ throws RepositoryException, RepositoryConfigurationException {
- this.extractor = extractor;
+ this.extractor = extractor;
- this.config = new QueryHandlerEntryWrapper(config);
- this.nodeTypeDataManager = ntReg;
- this.nsReg = nsReg;
- this.itemMgr = itemMgr;
- this.cfm = cfm;
+ this.config = new QueryHandlerEntryWrapper(config);
+ this.nodeTypeDataManager = ntReg;
+ this.nsReg = nsReg;
+ this.itemMgr = itemMgr;
+ this.cfm = cfm;
- this.parentSearchManager = parentSearchManager != null ? parentSearchManager.get() : null;
- itemMgr.addItemPersistenceListener(this);
+ this.parentSearchManager = parentSearchManager != null ? parentSearchManager
+ .get()
+ : null;
+ itemMgr.addItemPersistenceListener(this);
+ }
- //initializeQueryHandler();
- }
+ /**
+ * Creates a query object from a node that can be executed on the workspace.
+ *
+ * @param session
+ * the session of the user executing the query.
+ * @param itemMgr
+ * the item manager of the user executing the query. Needed to
+ * return <code>Node</code> instances in the result set.
+ * @param node
+ * a node of type nt:query.
+ * @return a <code>Query</code> instance to execute.
+ * @throws InvalidQueryException
+ * if <code>absPath</code> is not a valid persisted query (that
+ * is, a node of type nt:query)
+ * @throws RepositoryException
+ * if any other error occurs.
+ */
+ public Query createQuery(SessionImpl session,
+ SessionDataManager sessionDataManager, Node node)
+ throws InvalidQueryException, RepositoryException {
+ AbstractQueryImpl query = createQueryInstance();
+ query.init(session, sessionDataManager, handler, node);
+ return query;
+ }
- /**
- * Creates a query object from a node that can be executed on the workspace.
- *
- * @param session the session of the user executing the query.
- * @param itemMgr the item manager of the user executing the query. Needed to
- * return <code>Node</code> instances in the result set.
- * @param node a node of type nt:query.
- * @return a <code>Query</code> instance to execute.
- * @throws InvalidQueryException if <code>absPath</code> is not a valid
- * persisted query (that is, a node of type nt:query)
- * @throws RepositoryException if any other error occurs.
- */
- public Query createQuery(SessionImpl session, SessionDataManager sessionDataManager, Node node)
- throws InvalidQueryException, RepositoryException
- {
- AbstractQueryImpl query = createQueryInstance();
- query.init(session, sessionDataManager, handler, node);
- return query;
- }
+ /**
+ * Creates a query object that can be executed on the workspace.
+ *
+ * @param session
+ * the session of the user executing the query.
+ * @param itemMgr
+ * the item manager of the user executing the query. Needed to
+ * return <code>Node</code> instances in the result set.
+ * @param statement
+ * the actual query statement.
+ * @param language
+ * the syntax of the query statement.
+ * @return a <code>Query</code> instance to execute.
+ * @throws InvalidQueryException
+ * if the query is malformed or the <code>language</code> is
+ * unknown.
+ * @throws RepositoryException
+ * if any other error occurs.
+ */
+ public Query createQuery(SessionImpl session,
+ SessionDataManager sessionDataManager, String statement,
+ String language) throws InvalidQueryException, RepositoryException {
+ AbstractQueryImpl query = createQueryInstance();
+ query.init(session, sessionDataManager, handler, statement, language);
+ return query;
+ }
- /**
- * Creates a query object that can be executed on the workspace.
- *
- * @param session the session of the user executing the query.
- * @param itemMgr the item manager of the user executing the query. Needed to
- * return <code>Node</code> instances in the result set.
- * @param statement the actual query statement.
- * @param language the syntax of the query statement.
- * @return a <code>Query</code> instance to execute.
- * @throws InvalidQueryException if the query is malformed or the
- * <code>language</code> is unknown.
- * @throws RepositoryException if any other error occurs.
- */
- public Query createQuery(SessionImpl session, SessionDataManager sessionDataManager, String statement,
- String language) throws InvalidQueryException, RepositoryException
- {
- AbstractQueryImpl query = createQueryInstance();
- query.init(session, sessionDataManager, handler, statement, language);
- return query;
- }
+ /**
+ * just for test use only
+ */
+ public QueryHandler getHandler() {
- /**
- * just for test use only
- */
- public QueryHandler getHandler()
- {
+ return handler;
+ }
- return handler;
- }
+ public void onSaveItems(ItemStateChangesLog changesLog) {
+ if (handler == null)
+ return;
- public void onSaveItems(ItemStateChangesLog changesLog)
- {
- if (handler == null)
- return;
+ long time = System.currentTimeMillis();
- long time = System.currentTimeMillis();
+ // nodes that need to be removed from the index.
+ final Set<String> removedNodes = new HashSet<String>();
+ // nodes that need to be added to the index.
+ final Set<String> addedNodes = new HashSet<String>();
- // nodes that need to be removed from the index.
- final Set<String> removedNodes = new HashSet<String>();
- // nodes that need to be added to the index.
- final Set<String> addedNodes = new HashSet<String>();
+ final Map<String, List<ItemState>> updatedNodes = new HashMap<String, List<ItemState>>();
- final Map<String, List<ItemState>> updatedNodes = new HashMap<String, List<ItemState>>();
+ for (Iterator<ItemState> iter = changesLog.getAllStates().iterator(); iter
+ .hasNext();) {
+ ItemState itemState = iter.next();
- for (Iterator<ItemState> iter = changesLog.getAllStates().iterator(); iter.hasNext();)
- {
- ItemState itemState = iter.next();
+ if (!indexingTree.isExcluded(itemState)) {
+ String uuid = itemState.isNode() ? itemState.getData()
+ .getIdentifier() : itemState.getData()
+ .getParentIdentifier();
- if (!isExcluded(itemState))
- {
- String uuid =
- itemState.isNode() ? itemState.getData().getIdentifier() : itemState.getData().getParentIdentifier();
+ if (itemState.isAdded()) {
+ if (itemState.isNode()) {
+ addedNodes.add(uuid);
+ } else {
+ if (!addedNodes.contains(uuid)) {
+ createNewOrAdd(uuid, itemState, updatedNodes);
+ }
+ }
+ } else if (itemState.isRenamed()) {
+ if (itemState.isNode()) {
+ addedNodes.add(uuid);
+ } else {
+ createNewOrAdd(uuid, itemState, updatedNodes);
+ }
+ } else if (itemState.isUpdated()) {
+ createNewOrAdd(uuid, itemState, updatedNodes);
+ } else if (itemState.isMixinChanged()) {
+ createNewOrAdd(uuid, itemState, updatedNodes);
+ } else if (itemState.isDeleted()) {
+ if (itemState.isNode()) {
+ if (addedNodes.contains(uuid)) {
+ addedNodes.remove(uuid);
+ removedNodes.remove(uuid);
+ } else {
+ removedNodes.add(uuid);
+ }
+ // remove all changes after node remove
+ updatedNodes.remove(uuid);
+ } else {
+ if (!removedNodes.contains(uuid)
+ && !addedNodes.contains(uuid)) {
+ createNewOrAdd(uuid, itemState, updatedNodes);
+ }
+ }
+ }
+ }
+ }
+ // TODO make quick changes
+ for (String uuid : updatedNodes.keySet()) {
+ removedNodes.add(uuid);
+ addedNodes.add(uuid);
+ }
- if (itemState.isAdded())
- {
- if (itemState.isNode())
- {
- addedNodes.add(uuid);
- }
- else
- {
- if (!addedNodes.contains(uuid))
- {
- createNewOrAdd(uuid, itemState, updatedNodes);
- }
- }
- }
- else if (itemState.isRenamed())
- {
- if (itemState.isNode())
- {
- addedNodes.add(uuid);
- }
- else
- {
- createNewOrAdd(uuid, itemState, updatedNodes);
- }
- }
- else if (itemState.isUpdated())
- {
- createNewOrAdd(uuid, itemState, updatedNodes);
- }
- else if (itemState.isMixinChanged())
- {
- createNewOrAdd(uuid, itemState, updatedNodes);
- }
- else if (itemState.isDeleted())
- {
- if (itemState.isNode())
- {
- if (addedNodes.contains(uuid))
- {
- addedNodes.remove(uuid);
- removedNodes.remove(uuid);
- }
- else
- {
- removedNodes.add(uuid);
- }
- // remove all changes after node remove
- updatedNodes.remove(uuid);
- }
- else
- {
- if (!removedNodes.contains(uuid) && !addedNodes.contains(uuid))
- {
- createNewOrAdd(uuid, itemState, updatedNodes);
- }
- }
- }
- }
- }
- // TODO make quick changes
- for (String uuid : updatedNodes.keySet())
- {
- removedNodes.add(uuid);
- addedNodes.add(uuid);
- }
+ Iterator<NodeData> addedStates = new Iterator<NodeData>() {
+ private final Iterator<String> iter = addedNodes.iterator();
- Iterator<NodeData> addedStates = new Iterator<NodeData>()
- {
- private final Iterator<String> iter = addedNodes.iterator();
+ public boolean hasNext() {
+ return iter.hasNext();
+ }
- public boolean hasNext()
- {
- return iter.hasNext();
- }
+ public NodeData next() {
- public NodeData next()
- {
+ // cycle till find a next or meet the end of set
+ do {
+ String id = iter.next();
+ try {
+ ItemData item = itemMgr.getItemData(id);
+ if (item != null) {
+ if (item.isNode())
+ return (NodeData) item; // return node
+ else
+ log.warn("Node not found, but property " + id
+ + ", " + item.getQPath().getAsString()
+ + " found. ");
+ } else
+ log.warn("Unable to index node with id " + id
+ + ", node does not exist.");
- // cycle till find a next or meet the end of set
- do
- {
- String id = iter.next();
- try
- {
- ItemData item = itemMgr.getItemData(id);
- if (item != null)
- {
- if (item.isNode())
- return (NodeData)item; // return node
- else
- log.warn("Node not found, but property " + id + ", " + item.getQPath().getAsString()
- + " found. ");
- }
- else
- log.warn("Unable to index node with id " + id + ", node does not exist.");
+ } catch (RepositoryException e) {
+ log.error("Can't read next node data " + id, e);
+ }
+ } while (iter.hasNext()); // get next if error or node not found
- }
- catch (RepositoryException e)
- {
- log.error("Can't read next node data " + id, e);
- }
- }
- while (iter.hasNext()); // get next if error or node not found
+ return null; // we met the end of iterator set
+ }
- return null; // we met the end of iterator set
- }
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
- public void remove()
- {
- throw new UnsupportedOperationException();
- }
- };
+ Iterator<String> removedIds = new Iterator<String>() {
+ private final Iterator<String> iter = removedNodes.iterator();
- Iterator<String> removedIds = new Iterator<String>()
- {
- private final Iterator<String> iter = removedNodes.iterator();
+ public boolean hasNext() {
+ return iter.hasNext();
+ }
- public boolean hasNext()
- {
- return iter.hasNext();
- }
+ public String next() {
+ return nextNodeId();
+ }
- public String next()
- {
- return nextNodeId();
- }
+ public String nextNodeId() throws NoSuchElementException {
+ return iter.next();
+ }
- public String nextNodeId() throws NoSuchElementException
- {
- return iter.next();
- }
+ public void remove() {
+ throw new UnsupportedOperationException();
- public void remove()
- {
- throw new UnsupportedOperationException();
+ }
+ };
- }
- };
+ if (removedNodes.size() > 0 || addedNodes.size() > 0) {
+ try {
+ handler.updateNodes(removedIds, addedStates);
+ } catch (RepositoryException e) {
+ log.error("Error indexing changes " + e, e);
+ } catch (IOException e) {
+ log.error("Error indexing changes " + e, e);
+ try {
+ handler.logErrorChanges(removedNodes, addedNodes);
+ } catch (IOException ioe) {
+ log.warn(
+ "Exception occure when errorLog writed. Error log is not complete. "
+ + ioe, ioe);
+ }
+ }
+ }
- if (removedNodes.size() > 0 || addedNodes.size() > 0)
- {
- try
- {
- handler.updateNodes(removedIds, addedStates);
- }
- catch (RepositoryException e)
- {
- log.error("Error indexing changes " + e, e);
- }
- catch (IOException e)
- {
- log.error("Error indexing changes " + e, e);
- try
- {
- handler.logErrorChanges(removedNodes, addedNodes);
- }
- catch (IOException ioe)
- {
- log.warn("Exception occure when errorLog writed. Error log is not complete. " + ioe, ioe);
- }
- }
- }
+ if (log.isDebugEnabled()) {
+ log.debug("onEvent: indexing finished in "
+ + String.valueOf(System.currentTimeMillis() - time)
+ + " ms.");
+ }
+ }
- if (log.isDebugEnabled())
- {
- log.debug("onEvent: indexing finished in " + String.valueOf(System.currentTimeMillis() - time) + " ms.");
- }
- }
+ public void createNewOrAdd(String key, ItemState state,
+ Map<String, List<ItemState>> updatedNodes) {
+ List<ItemState> list = updatedNodes.get(key);
+ if (list == null) {
+ list = new ArrayList<ItemState>();
+ updatedNodes.put(key, list);
+ }
+ list.add(state);
- public void createNewOrAdd(String key, ItemState state, Map<String, List<ItemState>> updatedNodes)
- {
- List<ItemState> list = updatedNodes.get(key);
- if (list == null)
- {
- list = new ArrayList<ItemState>();
- updatedNodes.put(key, list);
- }
- list.add(state);
+ }
- }
+ public void start() {
- public void start()
- {
+ if (log.isDebugEnabled())
+ log.debug("start");
- if (log.isDebugEnabled())
- log.debug("start");
+ if (indexingTree == null) {
+ List<QPath> excludedPath = new ArrayList<QPath>();
+ // Calculating excluded node identifiers
+ excludedPath.add(Constants.JCR_SYSTEM_PATH);
- // Calculating excluded node identifiers
- excludedPaths.add(Constants.JCR_SYSTEM_PATH);
+ if (config.getExcludedNodeIdentifers() != null) {
+ StringTokenizer stringTokenizer = new StringTokenizer(config
+ .getExcludedNodeIdentifers());
+ while (stringTokenizer.hasMoreTokens()) {
- if (config.getExcludedNodeIdentifers() != null)
- {
- StringTokenizer stringTokenizer = new StringTokenizer(config.getExcludedNodeIdentifers());
- while (stringTokenizer.hasMoreTokens())
- {
+ try {
+ ItemData excludeData = itemMgr
+ .getItemData(stringTokenizer.nextToken());
+ if (excludeData != null)
+ excludedPath.add(excludeData.getQPath());
+ } catch (RepositoryException e) {
+ log.warn(e.getLocalizedMessage());
+ }
+ }
+ }
- try
- {
- ItemData excludeData = itemMgr.getItemData(stringTokenizer.nextToken());
- if (excludeData != null)
- excludedPaths.add(excludeData.getQPath());
- }
- catch (RepositoryException e)
- {
- log.warn(e.getLocalizedMessage());
- }
- }
- }
+ NodeData indexingRootData = null;
+ if (config.getRootNodeIdentifer() != null) {
+ try {
+ ItemData indexingRootDataItem = itemMgr.getItemData(config
+ .getRootNodeIdentifer());
+ if (indexingRootDataItem != null
+ && indexingRootDataItem.isNode())
+ indexingRootData = (NodeData) indexingRootDataItem;
+ } catch (RepositoryException e) {
+ log.warn(e.getLocalizedMessage() + " Indexing root set to "
+ + Constants.ROOT_PATH.getAsString());
- indexingRoot = Constants.ROOT_PATH;
- if (config.getRootNodeIdentifer() != null)
- {
- try
- {
- ItemData indexingRootData = itemMgr.getItemData(config.getRootNodeIdentifer());
- if (indexingRootData != null && indexingRootData.isNode())
- indexingRoot = indexingRootData.getQPath();
- }
- catch (RepositoryException e)
- {
- log.warn(e.getLocalizedMessage() + " Indexing root set to " + indexingRoot.getAsString());
- }
+ }
- }
- try
- {
- // handler.init(null);
- initializeQueryHandler();
+ } else {
+ try {
+ indexingRootData = (NodeData) itemMgr
+ .getItemData(Constants.ROOT_UUID);
+ } catch (RepositoryException e) {
+ log.error("Fail to load root node data");
+ }
+ }
- }
-// catch (IOException e)
-// {
-// log.error(e.getLocalizedMessage());
-// handler = null;
-// throw new RuntimeException(e.getLocalizedMessage(), e.getCause());
-// }
- catch (RepositoryException e)
- {
- log.error(e.getLocalizedMessage());
- handler = null;
- throw new RuntimeException(e.getLocalizedMessage(), e.getCause());
- }
- catch (RepositoryConfigurationException e)
- {
- log.error(e.getLocalizedMessage());
- handler = null;
- throw new RuntimeException(e.getLocalizedMessage(), e.getCause());
- }
- }
+ indexingTree = new IndexingTree(indexingRootData, excludedPath);
+ }
+ try {
+ initializeQueryHandler();
+ } catch (RepositoryException e) {
+ log.error(e.getLocalizedMessage());
+ handler = null;
+ throw new RuntimeException(e.getLocalizedMessage(), e.getCause());
+ } catch (RepositoryConfigurationException e) {
+ log.error(e.getLocalizedMessage());
+ handler = null;
+ throw new RuntimeException(e.getLocalizedMessage(), e.getCause());
+ }
+ }
- public void stop()
- {
- handler.close();
- log.info("Search manager stopped");
- }
+ public void stop() {
+ handler.close();
+ log.info("Search manager stopped");
+ }
- /**
- * Checks if the given event should be excluded based on the
- * {@link #excludePath} setting.
- *
- * @param event observation event
- * @return <code>true</code> if the event should be excluded,
- * <code>false</code> otherwise
- */
- protected boolean isExcluded(ItemState event)
- {
+ // /**
+ // * Checks if the given event should be excluded based on the
+ // * {@link #excludePath} setting.
+ // *
+ // * @param event
+ // * observation event
+ // * @return <code>true</code> if the event should be excluded,
+ // * <code>false</code> otherwise
+ // */
+ // protected boolean isExcluded(ItemState event) {
+ //
+ // for (QPath excludedPath : excludedPaths) {
+ // if (event.getData().getQPath().isDescendantOf(excludedPath)
+ // || event.getData().getQPath().equals(excludedPath))
+ // return true;
+ // }
+ //
+ // return !event.getData().getQPath().isDescendantOf(indexingRoot)
+ // && !event.getData().getQPath().equals(indexingRoot);
+ // }
- for (QPath excludedPath : excludedPaths)
- {
- if (event.getData().getQPath().isDescendantOf(excludedPath) || event.getData().getQPath().equals(excludedPath))
- return true;
- }
+ protected QueryHandlerContext createQueryHandlerContext(
+ QueryHandler parentHandler) throws RepositoryConfigurationException {
- return !event.getData().getQPath().isDescendantOf(indexingRoot)
- && !event.getData().getQPath().equals(indexingRoot);
- }
+ QueryHandlerContext context = new QueryHandlerContext(itemMgr,
+ indexingTree, nodeTypeDataManager, nsReg, parentHandler, config
+ .getIndexDir(), extractor, true);
+ return context;
+ }
- protected QueryHandlerContext createQueryHandlerContext(QueryHandler parentHandler)
- throws RepositoryConfigurationException
- {
+ /**
+ * Initializes the query handler.
+ *
+ * @throws RepositoryException
+ * if the query handler cannot be initialized.
+ * @throws RepositoryConfigurationException
+ * @throws ClassNotFoundException
+ */
+ protected void initializeQueryHandler() throws RepositoryException,
+ RepositoryConfigurationException {
+ // initialize query handler
+ String className = config.getType();
+ if (className == null)
+ throw new RepositoryConfigurationException(
+ "Content hanler configuration fail");
- QueryHandlerContext context =
- new QueryHandlerContext(itemMgr, config.getRootNodeIdentifer() != null ? config.getRootNodeIdentifer()
- : Constants.ROOT_UUID, nodeTypeDataManager, nsReg, parentHandler, config.getIndexDir(), extractor);
- return context;
- }
+ try {
+ Class qHandlerClass = Class.forName(className, true, this
+ .getClass().getClassLoader());
+ Constructor constuctor = qHandlerClass.getConstructor(
+ QueryHandlerEntry.class, ConfigurationManager.class);
+ handler = (QueryHandler) constuctor.newInstance(config
+ .getQueryHandlerEntry(), cfm);
+ QueryHandler parentHandler = (this.parentSearchManager != null) ? parentSearchManager
+ .getHandler()
+ : null;
+ QueryHandlerContext context = createQueryHandlerContext(parentHandler);
+ handler.init(context);
- /**
- * Initializes the query handler.
- *
- * @throws RepositoryException if the query handler cannot be initialized.
- * @throws RepositoryConfigurationException
- * @throws ClassNotFoundException
- */
- protected void initializeQueryHandler() throws RepositoryException, RepositoryConfigurationException
- {
- // initialize query handler
- String className = config.getType();
- if (className == null)
- throw new RepositoryConfigurationException("Content hanler configuration fail");
+ } catch (SecurityException e) {
+ throw new RepositoryException(e.getMessage(), e);
+ } catch (IllegalArgumentException e) {
+ throw new RepositoryException(e.getMessage(), e);
+ } catch (ClassNotFoundException e) {
+ throw new RepositoryException(e.getMessage(), e);
+ } catch (NoSuchMethodException e) {
+ throw new RepositoryException(e.getMessage(), e);
+ } catch (InstantiationException e) {
+ throw new RepositoryException(e.getMessage(), e);
+ } catch (IllegalAccessException e) {
+ throw new RepositoryException(e.getMessage(), e);
+ } catch (InvocationTargetException e) {
+ throw new RepositoryException(e.getMessage(), e);
+ } catch (IOException e) {
+ throw new RepositoryException(e.getMessage(), e);
+ }
+ }
- try
- {
- Class qHandlerClass = Class.forName(className, true, this.getClass().getClassLoader());
- Constructor constuctor = qHandlerClass.getConstructor(QueryHandlerEntry.class, ConfigurationManager.class);
- handler = (QueryHandler)constuctor.newInstance(config.getQueryHandlerEntry(), cfm);
- QueryHandler parentHandler = (this.parentSearchManager != null) ? parentSearchManager.getHandler() : null;
- QueryHandlerContext context = createQueryHandlerContext(parentHandler);
- handler.init(context);
- }
- catch (SecurityException e)
- {
- throw new RepositoryException(e.getMessage(), e);
- }
- catch (IllegalArgumentException e)
- {
- throw new RepositoryException(e.getMessage(), e);
- }
- catch (ClassNotFoundException e)
- {
- throw new RepositoryException(e.getMessage(), e);
- }
- catch (NoSuchMethodException e)
- {
- throw new RepositoryException(e.getMessage(), e);
- }
- catch (InstantiationException e)
- {
- throw new RepositoryException(e.getMessage(), e);
- }
- catch (IllegalAccessException e)
- {
- throw new RepositoryException(e.getMessage(), e);
- }
- catch (InvocationTargetException e)
- {
- throw new RepositoryException(e.getMessage(), e);
- }
- catch (IOException e)
- {
- throw new RepositoryException(e.getMessage(), e);
- }
- }
- /**
- * Creates a new instance of an {@link AbstractQueryImpl} which is not
- * initialized.
- *
- * @return an new query instance.
- * @throws RepositoryException if an error occurs while creating a new query
- * instance.
- */
- protected AbstractQueryImpl createQueryInstance() throws RepositoryException {
- try {
- String queryImplClassName = handler.getQueryClass();
- Object obj = Class.forName(queryImplClassName).newInstance();
- if (obj instanceof AbstractQueryImpl) {
- return (AbstractQueryImpl) obj;
- } else {
- throw new IllegalArgumentException(queryImplClassName
- + " is not of type " + AbstractQueryImpl.class.getName());
- }
- } catch (Throwable t) {
- throw new RepositoryException("Unable to create query: " + t.toString(), t);
- }
- }
+ /**
+ * Creates a new instance of an {@link AbstractQueryImpl} which is not
+ * initialized.
+ *
+ * @return an new query instance.
+ * @throws RepositoryException
+ * if an error occurs while creating a new query instance.
+ */
+ protected AbstractQueryImpl createQueryInstance()
+ throws RepositoryException {
+ try {
+ String queryImplClassName = handler.getQueryClass();
+ Object obj = Class.forName(queryImplClassName).newInstance();
+ if (obj instanceof AbstractQueryImpl) {
+ return (AbstractQueryImpl) obj;
+ } else {
+ throw new IllegalArgumentException(queryImplClassName
+ + " is not of type "
+ + AbstractQueryImpl.class.getName());
+ }
+ } catch (Throwable t) {
+ throw new RepositoryException("Unable to create query: "
+ + t.toString(), t);
+ }
+ }
}
Modified: jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/SystemSearchManager.java
===================================================================
--- jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/SystemSearchManager.java 2009-10-01 15:37:53 UTC (rev 193)
+++ jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/SystemSearchManager.java 2009-10-02 08:25:49 UTC (rev 194)
@@ -22,13 +22,14 @@
import org.exoplatform.services.jcr.config.RepositoryConfigurationException;
import org.exoplatform.services.jcr.core.nodetype.NodeTypeDataManager;
import org.exoplatform.services.jcr.dataflow.ItemStateChangesLog;
+import org.exoplatform.services.jcr.datamodel.NodeData;
+import org.exoplatform.services.jcr.datamodel.QPath;
import org.exoplatform.services.jcr.impl.Constants;
import org.exoplatform.services.jcr.impl.core.NamespaceRegistryImpl;
import org.exoplatform.services.jcr.impl.dataflow.persistent.WorkspacePersistentDataManager;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
-import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@@ -41,98 +42,89 @@
* @version $Id: SystemSearchManager.java 13891 2008-05-05 16:02:30Z pnedonosko
* $
*/
-public class SystemSearchManager extends SearchManager
-{
+public class SystemSearchManager extends SearchManager {
- /**
- * Class logger.
- */
- private final Log log = ExoLogger.getLogger("jcr.SystemSearchManager");
+ /**
+ * Class logger.
+ */
+ private final Log log = ExoLogger.getLogger("jcr.SystemSearchManager");
- /**
- * Is started flag.
- */
- private boolean isStarted = false;
+ /**
+ * Is started flag.
+ */
+ private boolean isStarted = false;
- /**
- * ChangesLog Buffer (used for saves before start).
- */
- private List<ItemStateChangesLog> changesLogBuffer = new ArrayList<ItemStateChangesLog>();
+ /**
+ * ChangesLog Buffer (used for saves before start).
+ */
+ private List<ItemStateChangesLog> changesLogBuffer = new ArrayList<ItemStateChangesLog>();
- public static final String INDEX_DIR_SUFFIX = "system";
+ public static final String INDEX_DIR_SUFFIX = "system";
- public SystemSearchManager(QueryHandlerEntry config, NamespaceRegistryImpl nsReg, NodeTypeDataManager ntReg,
- WorkspacePersistentDataManager itemMgr, DocumentReaderService service, ConfigurationManager cfm)
- throws RepositoryException, RepositoryConfigurationException
- {
- super(config, nsReg, ntReg, itemMgr, null, service, cfm);
- }
+ public SystemSearchManager(QueryHandlerEntry config,
+ NamespaceRegistryImpl nsReg, NodeTypeDataManager ntReg,
+ WorkspacePersistentDataManager itemMgr,
+ DocumentReaderService service, ConfigurationManager cfm)
+ throws RepositoryException, RepositoryConfigurationException {
+ super(config, nsReg, ntReg, itemMgr, null, service, cfm);
+ }
- @Override
- public void onSaveItems(ItemStateChangesLog changesLog)
- {
- if (!isStarted)
- {
- changesLogBuffer.add(changesLog);
- }
- else
- {
- super.onSaveItems(changesLog);
- }
- }
+ @Override
+ public void onSaveItems(ItemStateChangesLog changesLog) {
+ if (!isStarted) {
+ changesLogBuffer.add(changesLog);
+ } else {
+ super.onSaveItems(changesLog);
+ }
+ }
- @Override
- public void start()
- {
- indexingRoot = Constants.JCR_SYSTEM_PATH;
- excludedPaths.remove(Constants.JCR_SYSTEM_PATH);
- isStarted = true;
- try
- {
- //handler.init(null);
- initializeQueryHandler();
+ @Override
+ public void start() {
- }
-// catch (IOException e)
-// {
-// log.error(e.getLocalizedMessage());
-// handler = null;
-// changesLogBuffer.clear();
-// changesLogBuffer = null;
-// throw new RuntimeException(e);
-// }
- catch (RepositoryException e)
- {
- log.error(e.getLocalizedMessage());
- handler = null;
- changesLogBuffer.clear();
- changesLogBuffer = null;
- throw new RuntimeException(e);
- }
- catch (RepositoryConfigurationException e)
- {
- log.error(e.getLocalizedMessage());
- handler = null;
- changesLogBuffer.clear();
- changesLogBuffer = null;
- throw new RuntimeException(e);
- }
- for (ItemStateChangesLog bufferedChangesLog : changesLogBuffer)
- {
- super.onSaveItems(bufferedChangesLog);
- }
- changesLogBuffer.clear();
- changesLogBuffer = null;
- }
+ isStarted = true;
+ try {
+ if (indexingTree == null) {
+ List<QPath> excludedPaths = new ArrayList<QPath>();
- @Override
- protected QueryHandlerContext createQueryHandlerContext(QueryHandler parentHandler)
- throws RepositoryConfigurationException
- {
- QueryHandlerContext context =
- new QueryHandlerContext(itemMgr, Constants.SYSTEM_UUID, nodeTypeDataManager, nsReg, parentHandler, config
- .getIndexDir()
- + "_" + INDEX_DIR_SUFFIX, extractor);
- return context;
- }
+ NodeData indexingRootNodeData = (NodeData) itemMgr
+ .getItemData(Constants.SYSTEM_UUID);
+
+ indexingTree = new IndexingTree(indexingRootNodeData,
+ excludedPaths);
+ }
+ initializeQueryHandler();
+
+ }
+
+ catch (RepositoryException e) {
+ log.error(e.getLocalizedMessage());
+ handler = null;
+ changesLogBuffer.clear();
+ changesLogBuffer = null;
+ throw new RuntimeException(e);
+ } catch (RepositoryConfigurationException e) {
+ log.error(e.getLocalizedMessage());
+ handler = null;
+ changesLogBuffer.clear();
+ changesLogBuffer = null;
+ throw new RuntimeException(e);
+ }
+ for (ItemStateChangesLog bufferedChangesLog : changesLogBuffer) {
+ super.onSaveItems(bufferedChangesLog);
+ }
+ changesLogBuffer.clear();
+ changesLogBuffer = null;
+ }
+
+ @Override
+ protected QueryHandlerContext createQueryHandlerContext(
+ QueryHandler parentHandler) throws RepositoryConfigurationException {
+ QueryHandlerContext context = new QueryHandlerContext(itemMgr,
+ indexingTree, nodeTypeDataManager, nsReg, parentHandler, config
+ .getIndexDir()
+ + "_" + INDEX_DIR_SUFFIX, extractor, changesLogBuffer
+ .size() > 0
+ && !isStarted);
+ return context;
+ }
}
Modified: jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/MultiIndex.java
===================================================================
--- jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/MultiIndex.java 2009-10-01 15:37:53 UTC (rev 193)
+++ jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/MultiIndex.java 2009-10-02 08:25:49 UTC (rev 194)
@@ -16,6 +16,19 @@
*/
package org.exoplatform.services.jcr.impl.core.query.lucene;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.store.Directory;
+import org.exoplatform.services.jcr.dataflow.ItemDataConsumer;
+import org.exoplatform.services.jcr.datamodel.ItemData;
+import org.exoplatform.services.jcr.datamodel.NodeData;
+import org.exoplatform.services.jcr.impl.Constants;
+import org.exoplatform.services.jcr.impl.core.query.IndexingTree;
+import org.exoplatform.services.jcr.impl.core.query.lucene.directory.DirectoryManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
@@ -33,37 +46,25 @@
import javax.jcr.ItemNotFoundException;
import javax.jcr.RepositoryException;
-import org.apache.lucene.document.Document;
-import org.apache.lucene.index.IndexReader;
-import org.apache.lucene.index.Term;
-import org.apache.lucene.store.Directory;
-
-import org.exoplatform.services.jcr.dataflow.ItemDataConsumer;
-import org.exoplatform.services.jcr.datamodel.ItemData;
-import org.exoplatform.services.jcr.datamodel.NodeData;
-import org.exoplatform.services.jcr.impl.Constants;
-import org.exoplatform.services.jcr.impl.core.query.lucene.directory.DirectoryManager;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
/**
* A <code>MultiIndex</code> consists of a {@link VolatileIndex} and multiple
* {@link PersistentIndex}es. The goal is to keep most parts of the index open
- * with index readers and write new index data to the volatile index. When
- * the volatile index reaches a certain size (see {@link SearchIndex#setMinMergeDocs(int)})
- * a new persistent index is created with the index data from the volatile index,
- * the same happens when the volatile index has been idle for some time (see
- * {@link SearchIndex#setVolatileIdleTime(int)}).
- * The new persistent index is then added to the list of already existing
- * persistent indexes. Further operations on the new persistent index will
- * however only require an <code>IndexReader</code> which serves for queries
- * but also for delete operations on the index.
+ * with index readers and write new index data to the volatile index. When the
+ * volatile index reaches a certain size (see
+ * {@link SearchIndex#setMinMergeDocs(int)}) a new persistent index is created
+ * with the index data from the volatile index, the same happens when the
+ * volatile index has been idle for some time (see
+ * {@link SearchIndex#setVolatileIdleTime(int)}). The new persistent index is
+ * then added to the list of already existing persistent indexes. Further
+ * operations on the new persistent index will however only require an
+ * <code>IndexReader</code> which serves for queries but also for delete
+ * operations on the index.
* <p/>
- * The persistent indexes are merged from time to time. The merge behaviour
- * is configurable using the methods: {@link SearchIndex#setMaxMergeDocs(int)},
- * {@link SearchIndex#setMergeFactor(int)} and {@link SearchIndex#setMinMergeDocs(int)}.
- * For detailed description of the configuration parameters see also the lucene
- * <code>IndexWriter</code> class.
+ * The persistent indexes are merged from time to time. The merge behaviour is
+ * configurable using the methods: {@link SearchIndex#setMaxMergeDocs(int)},
+ * {@link SearchIndex#setMergeFactor(int)} and
+ * {@link SearchIndex#setMinMergeDocs(int)}. For detailed description of the
+ * configuration parameters see also the lucene <code>IndexWriter</code> class.
* <p/>
* This class is thread-safe.
* <p/>
@@ -72,2175 +73,2024 @@
* thread and reader threads is done using {@link #updateMonitor} and
* {@link #updateInProgress}.
*/
-public class MultiIndex
-{
+public class MultiIndex {
- /**
- * The logger instance for this class
- */
- private static final Logger log = LoggerFactory.getLogger(MultiIndex.class);
+ /**
+ * The logger instance for this class
+ */
+ private static final Logger log = LoggerFactory.getLogger(MultiIndex.class);
- // /**
- // * A path factory.
- // */
- // private static final PathFactory PATH_FACTORY = PathFactoryImpl.getInstance();
+ /**
+ * Names of active persistent index directories.
+ */
+ private final IndexInfos indexNames = new IndexInfos("indexes");
- /**
- * Names of active persistent index directories.
- */
- private final IndexInfos indexNames = new IndexInfos("indexes");
+ /**
+ * Names of index directories that can be deleted.
+ */
+ private final Set deletable = new HashSet();
- /**
- * Names of index directories that can be deleted.
- */
- private final Set deletable = new HashSet();
+ /**
+ * List of open persistent indexes. This list may also contain an open
+ * PersistentIndex owned by the IndexMerger daemon. Such an index is not
+ * registered with indexNames and <b>must not</b> be used in regular index
+ * operations (delete node, etc.)!
+ */
+ private final List indexes = new ArrayList();
- /**
- * List of open persistent indexes. This list may also contain an open
- * PersistentIndex owned by the IndexMerger daemon. Such an index is not
- * registered with indexNames and <b>must not</b> be used in regular index
- * operations (delete node, etc.)!
- */
- private final List indexes = new ArrayList();
+ /**
+ * The internal namespace mappings of the query manager.
+ */
+ private final NamespaceMappings nsMappings;
- /**
- * The internal namespace mappings of the query manager.
- */
- private final NamespaceMappings nsMappings;
+ /**
+ * The directory manager.
+ */
+ private final DirectoryManager directoryManager;
- /**
- * The directory manager.
- */
- private final DirectoryManager directoryManager;
+ /**
+ * The base directory to store the index.
+ */
+ private final Directory indexDir;
- /**
- * The base directory to store the index.
- */
- private final Directory indexDir;
+ /**
+ * The query handler
+ */
+ private final SearchIndex handler;
- /**
- * The query handler
- */
- private final SearchIndex handler;
+ /**
+ * The volatile index.
+ */
+ private VolatileIndex volatileIndex;
- /**
- * The volatile index.
- */
- private VolatileIndex volatileIndex;
+ /**
+ * Flag indicating whether an update operation is in progress.
+ */
+ private boolean updateInProgress = false;
- /**
- * Flag indicating whether an update operation is in progress.
- */
- private boolean updateInProgress = false;
+ /**
+ * If not <code>null</code> points to a valid <code>IndexReader</code> that
+ * reads from all indexes, including volatile and persistent indexes.
+ */
+ private CachingMultiIndexReader multiReader;
- /**
- * If not <code>null</code> points to a valid <code>IndexReader</code> that
- * reads from all indexes, including volatile and persistent indexes.
- */
- private CachingMultiIndexReader multiReader;
+ /**
+ * Shared document number cache across all persistent indexes.
+ */
+ private final DocNumberCache cache;
- /**
- * Shared document number cache across all persistent indexes.
- */
- private final DocNumberCache cache;
+ /**
+ * Monitor to use to synchronize access to {@link #multiReader} and
+ * {@link #updateInProgress}.
+ */
+ private final Object updateMonitor = new Object();
- /**
- * Monitor to use to synchronize access to {@link #multiReader} and
- * {@link #updateInProgress}.
- */
- private final Object updateMonitor = new Object();
+ /**
+ * <code>true</code> if the redo log contained entries on startup.
+ */
+ private boolean redoLogApplied = false;
- /**
- * <code>true</code> if the redo log contained entries on startup.
- */
- private boolean redoLogApplied = false;
+ /**
+ * The time this index was last flushed or a transaction was committed.
+ */
+ private long lastFlushTime;
- /**
- * The time this index was last flushed or a transaction was committed.
- */
- private long lastFlushTime;
+ /**
+ * The <code>IndexMerger</code> for this <code>MultiIndex</code>.
+ */
+ private final IndexMerger merger;
- /**
- * The <code>IndexMerger</code> for this <code>MultiIndex</code>.
- */
- private final IndexMerger merger;
+ /**
+ * Timer to schedule flushes of this index after some idle time.
+ */
+ private static final Timer FLUSH_TIMER = new Timer(true);
- /**
- * Timer to schedule flushes of this index after some idle time.
- */
- private static final Timer FLUSH_TIMER = new Timer(true);
+ /**
+ * Task that is periodically called by {@link #FLUSH_TIMER} and checks if
+ * index should be flushed.
+ */
+ private final TimerTask flushTask;
- /**
- * Task that is periodically called by {@link #FLUSH_TIMER} and checks
- * if index should be flushed.
- */
- private final TimerTask flushTask;
+ /**
+ * The RedoLog of this <code>MultiIndex</code>.
+ */
+ private final RedoLog redoLog;
- /**
- * The RedoLog of this <code>MultiIndex</code>.
- */
- private final RedoLog redoLog;
+ /**
+ * The indexing queue with pending text extraction jobs.
+ */
+ private IndexingQueue indexingQueue;
- /**
- * The indexing queue with pending text extraction jobs.
- */
- private IndexingQueue indexingQueue;
+ /**
+ * Set<NodeId> of uuids that should not be indexed.
+ */
+ private final IndexingTree indexingTree;
- /**
- * Set<NodeId> of uuids that should not be indexed.
- */
- private final Set excludedIDs;
+ /**
+ * The next transaction id.
+ */
+ private long nextTransactionId = 0;
- /**
- * The next transaction id.
- */
- private long nextTransactionId = 0;
+ /**
+ * The current transaction id.
+ */
+ private long currentTransactionId = -1;
- /**
- * The current transaction id.
- */
- private long currentTransactionId = -1;
+ /**
+ * Flag indicating whether re-indexing is running.
+ */
+ private boolean reindexing = false;
- /**
- * Flag indicating whether re-indexing is running.
- */
- private boolean reindexing = false;
+ /**
+ * The index format version of this multi index.
+ */
+ private final IndexFormatVersion version;
- /**
- * The index format version of this multi index.
- */
- private final IndexFormatVersion version;
+ /**
+ * Creates a new MultiIndex.
+ *
+ * @param handler
+ * the search handler
+ * @param excludedIDs
+ * Set<NodeId> that contains uuids that should not be indexed
+ * nor further traversed.
+ * @throws IOException
+ * if an error occurs
+ */
+ MultiIndex(SearchIndex handler, IndexingTree indexingTree)
+ throws IOException {
+ this.directoryManager = handler.getDirectoryManager();
+ this.indexDir = directoryManager.getDirectory(".");
+ this.handler = handler;
+ this.cache = new DocNumberCache(handler.getCacheSize());
+ this.redoLog = new RedoLog(indexDir);
+ this.indexingTree = indexingTree;
+ this.nsMappings = handler.getNamespaceMappings();
- /**
- * Creates a new MultiIndex.
- *
- * @param handler the search handler
- * @param excludedIDs Set<NodeId> that contains uuids that should not
- * be indexed nor further traversed.
- * @throws IOException if an error occurs
- */
- MultiIndex(SearchIndex handler, Set excludedIDs) throws IOException
- {
- this.directoryManager = handler.getDirectoryManager();
- this.indexDir = directoryManager.getDirectory(".");
- this.handler = handler;
- this.cache = new DocNumberCache(handler.getCacheSize());
- this.redoLog = new RedoLog(indexDir);
- this.excludedIDs = new HashSet(excludedIDs);
- this.nsMappings = handler.getNamespaceMappings();
+ if (indexNames.exists(indexDir)) {
+ indexNames.read(indexDir);
+ }
- if (indexNames.exists(indexDir))
- {
- indexNames.read(indexDir);
- }
+ // as of 1.5 deletable file is not used anymore
+ removeDeletable();
- // as of 1.5 deletable file is not used anymore
- removeDeletable();
+ // initialize IndexMerger
+ merger = new IndexMerger(this);
+ merger.setMaxMergeDocs(handler.getMaxMergeDocs());
+ merger.setMergeFactor(handler.getMergeFactor());
+ merger.setMinMergeDocs(handler.getMinMergeDocs());
- // initialize IndexMerger
- merger = new IndexMerger(this);
- merger.setMaxMergeDocs(handler.getMaxMergeDocs());
- merger.setMergeFactor(handler.getMergeFactor());
- merger.setMinMergeDocs(handler.getMinMergeDocs());
+ IndexingQueueStore store = new IndexingQueueStore(indexDir);
- IndexingQueueStore store = new IndexingQueueStore(indexDir);
+ // initialize indexing queue
+ this.indexingQueue = new IndexingQueue(store);
- // initialize indexing queue
- this.indexingQueue = new IndexingQueue(store);
+ // open persistent indexes
+ for (int i = 0; i < indexNames.size(); i++) {
+ String name = indexNames.getName(i);
+ // only open if it still exists
+ // it is possible that indexNames still contains a name for
+ // an index that has been deleted, but indexNames has not been
+ // written to disk.
+ if (!directoryManager.hasDirectory(name)) {
+ log.debug("index does not exist anymore: " + name);
+ // move on to next index
+ continue;
+ }
+ PersistentIndex index = new PersistentIndex(name, handler
+ .getTextAnalyzer(), handler.getSimilarity(), cache,
+ indexingQueue, directoryManager);
+ index.setMaxFieldLength(handler.getMaxFieldLength());
+ index.setUseCompoundFile(handler.getUseCompoundFile());
+ index.setTermInfosIndexDivisor(handler.getTermInfosIndexDivisor());
+ indexes.add(index);
+ merger.indexAdded(index.getName(), index.getNumDocuments());
+ }
- // open persistent indexes
- for (int i = 0; i < indexNames.size(); i++)
- {
- String name = indexNames.getName(i);
- // only open if it still exists
- // it is possible that indexNames still contains a name for
- // an index that has been deleted, but indexNames has not been
- // written to disk.
- if (!directoryManager.hasDirectory(name))
- {
- log.debug("index does not exist anymore: " + name);
- // move on to next index
- continue;
- }
- PersistentIndex index =
- new PersistentIndex(name, handler.getTextAnalyzer(), handler.getSimilarity(), cache, indexingQueue,
- directoryManager);
- index.setMaxFieldLength(handler.getMaxFieldLength());
- index.setUseCompoundFile(handler.getUseCompoundFile());
- index.setTermInfosIndexDivisor(handler.getTermInfosIndexDivisor());
- indexes.add(index);
- merger.indexAdded(index.getName(), index.getNumDocuments());
- }
+ // init volatile index
+ resetVolatileIndex();
- // init volatile index
- resetVolatileIndex();
+ // set index format version and at the same time
+ // initialize hierarchy cache if requested.
+ CachingMultiIndexReader reader = getIndexReader(handler
+ .isInitializeHierarchyCache());
+ try {
+ version = IndexFormatVersion.getVersion(reader);
+ } finally {
+ reader.release();
+ }
- // set index format version and at the same time
- // initialize hierarchy cache if requested.
- CachingMultiIndexReader reader = getIndexReader(handler.isInitializeHierarchyCache());
- try
- {
- version = IndexFormatVersion.getVersion(reader);
- }
- finally
- {
- reader.release();
- }
+ indexingQueue.initialize(this);
- indexingQueue.initialize(this);
+ redoLogApplied = redoLog.hasEntries();
- redoLogApplied = redoLog.hasEntries();
+ // run recovery
+ Recovery.run(this, redoLog);
- // run recovery
- Recovery.run(this, redoLog);
+ // enqueue unused segments for deletion
+ enqueueUnusedSegments();
+ attemptDelete();
- // enqueue unused segments for deletion
- enqueueUnusedSegments();
- attemptDelete();
+ // now that we are ready, start index merger
+ merger.start();
- // now that we are ready, start index merger
- merger.start();
+ if (redoLogApplied) {
+ // wait for the index merge to finish pending jobs
+ try {
+ merger.waitUntilIdle();
+ } catch (InterruptedException e) {
+ // move on
+ }
+ flush();
+ }
- if (redoLogApplied)
- {
- // wait for the index merge to finish pending jobs
- try
- {
- merger.waitUntilIdle();
- }
- catch (InterruptedException e)
- {
- // move on
- }
- flush();
- }
+ flushTask = new TimerTask() {
+ public void run() {
+ // check if there are any indexing jobs finished
+ checkIndexingQueue();
+ // check if volatile index should be flushed
+ checkFlush();
+ }
+ };
- flushTask = new TimerTask()
- {
- public void run()
- {
- // check if there are any indexing jobs finished
- checkIndexingQueue();
- // check if volatile index should be flushed
- checkFlush();
- }
- };
+ if (indexNames.size() > 0) {
+ scheduleFlushTask();
+ }
+ }
- if (indexNames.size() > 0)
- {
- scheduleFlushTask();
- }
- }
+ /**
+ * Returns the number of documents in this index.
+ *
+ * @return the number of documents in this index.
+ * @throws IOException
+ * if an error occurs while reading from the index.
+ */
+ int numDocs() throws IOException {
+ if (indexNames.size() == 0) {
+ return volatileIndex.getNumDocuments();
+ } else {
+ CachingMultiIndexReader reader = getIndexReader();
+ try {
+ return reader.numDocs();
+ } finally {
+ reader.release();
+ }
+ }
+ }
- /**
- * Returns the number of documents in this index.
- *
- * @return the number of documents in this index.
- * @throws IOException if an error occurs while reading from the index.
- */
- int numDocs() throws IOException
- {
- if (indexNames.size() == 0)
- {
- return volatileIndex.getNumDocuments();
- }
- else
- {
- CachingMultiIndexReader reader = getIndexReader();
- try
- {
- return reader.numDocs();
- }
- finally
- {
- reader.release();
- }
- }
- }
+ /**
+ * @return the index format version for this multi index.
+ */
+ IndexFormatVersion getIndexFormatVersion() {
+ return version;
+ }
- /**
- * @return the index format version for this multi index.
- */
- IndexFormatVersion getIndexFormatVersion()
- {
- return version;
- }
+ /**
+ * Creates an initial index by traversing the node hierarchy starting at the
+ * node with <code>rootId</code>.
+ *
+ * @param stateMgr
+ * the item state manager.
+ * @param rootId
+ * the id of the node from where to start.
+ * @param rootPath
+ * the path of the node from where to start.
+ * @throws IOException
+ * if an error occurs while indexing the workspace.
+ * @throws IllegalStateException
+ * if this index is not empty.
+ */
+ void createInitialIndex(ItemDataConsumer stateMgr) throws IOException {
+ // only do an initial index if there are no indexes at all
+ if (indexNames.size() == 0) {
+ reindexing = true;
+ try {
+ long count = 0;
+ // traverse and index workspace
+ executeAndLog(new Start(Action.INTERNAL_TRANSACTION));
+ // NodeData rootState = (NodeData) stateMgr.getItemData(rootId);
+ count = createIndex(indexingTree.getIndexingRoot(), stateMgr,
+ count);
+ executeAndLog(new Commit(getTransactionId()));
+ log.info("Created initial index for {} nodes", new Long(count));
+ releaseMultiReader();
+ scheduleFlushTask();
+ } catch (Exception e) {
+ String msg = "Error indexing workspace";
+ IOException ex = new IOException(msg);
+ ex.initCause(e);
+ throw ex;
+ } finally {
+ reindexing = false;
+ }
+ } else {
+ throw new IllegalStateException("Index already present");
+ }
+ }
- /**
- * Creates an initial index by traversing the node hierarchy starting at the
- * node with <code>rootId</code>.
- *
- * @param stateMgr the item state manager.
- * @param rootId the id of the node from where to start.
- * @param rootPath the path of the node from where to start.
- * @throws IOException if an error occurs while indexing the
- * workspace.
- * @throws IllegalStateException if this index is not empty.
- */
- void createInitialIndex(ItemDataConsumer stateMgr, String rootId) throws IOException
- {
- // only do an initial index if there are no indexes at all
- if (indexNames.size() == 0)
- {
- reindexing = true;
- try
- {
- long count = 0;
- // traverse and index workspace
- executeAndLog(new Start(Action.INTERNAL_TRANSACTION));
- NodeData rootState = (NodeData)stateMgr.getItemData(rootId);
- count = createIndex(rootState, stateMgr, count);
- executeAndLog(new Commit(getTransactionId()));
- log.info("Created initial index for {} nodes", new Long(count));
- releaseMultiReader();
- scheduleFlushTask();
- }
- catch (Exception e)
- {
- String msg = "Error indexing workspace";
- IOException ex = new IOException(msg);
- ex.initCause(e);
- throw ex;
- }
- finally
- {
- reindexing = false;
- }
- }
- else
- {
- throw new IllegalStateException("Index already present");
- }
- }
+ /**
+ * Atomically updates the index by removing some documents and adding
+ * others.
+ *
+ * @param remove
+ * collection of <code>UUID</code>s that identify documents to
+ * remove
+ * @param add
+ * collection of <code>Document</code>s to add. Some of the
+ * elements in this collection may be <code>null</code>, to
+ * indicate that a node could not be indexed successfully.
+ * @throws IOException
+ * if an error occurs while updating the index.
+ */
+ synchronized void update(Collection remove, Collection add)
+ throws IOException {
+ // make sure a reader is available during long updates
+ if (add.size() > handler.getBufferSize()) {
+ try {
+ getIndexReader().release();
+ } catch (IOException e) {
+ // do not fail if an exception is thrown here
+ log.warn("unable to prepare index reader "
+ + "for queries during update", e);
+ }
+ }
- /**
- * Atomically updates the index by removing some documents and adding
- * others.
- *
- * @param remove collection of <code>UUID</code>s that identify documents to
- * remove
- * @param add collection of <code>Document</code>s to add. Some of the
- * elements in this collection may be <code>null</code>, to
- * indicate that a node could not be indexed successfully.
- * @throws IOException if an error occurs while updating the index.
- */
- synchronized void update(Collection remove, Collection add) throws IOException
- {
- // make sure a reader is available during long updates
- if (add.size() > handler.getBufferSize())
- {
- try
- {
- getIndexReader().release();
- }
- catch (IOException e)
- {
- // do not fail if an exception is thrown here
- log.warn("unable to prepare index reader for queries during update", e);
- }
- }
+ synchronized (updateMonitor) {
+ updateInProgress = true;
+ }
+ try {
+ long transactionId = nextTransactionId++;
+ executeAndLog(new Start(transactionId));
- synchronized (updateMonitor)
- {
- updateInProgress = true;
- }
- try
- {
- long transactionId = nextTransactionId++;
- executeAndLog(new Start(transactionId));
+ boolean flush = false;
+ for (Iterator it = remove.iterator(); it.hasNext();) {
+ executeAndLog(new DeleteNode(transactionId, (String) it.next()));
+ }
+ for (Iterator it = add.iterator(); it.hasNext();) {
+ Document doc = (Document) it.next();
+ if (doc != null) {
+ executeAndLog(new AddNode(transactionId, doc));
+ // commit volatile index if needed
+ flush |= checkVolatileCommit();
+ }
+ }
+ executeAndLog(new Commit(transactionId));
- boolean flush = false;
- for (Iterator it = remove.iterator(); it.hasNext();)
- {
- executeAndLog(new DeleteNode(transactionId, (String)it.next()));
- }
- for (Iterator it = add.iterator(); it.hasNext();)
- {
- Document doc = (Document)it.next();
- if (doc != null)
- {
- executeAndLog(new AddNode(transactionId, doc));
- // commit volatile index if needed
- flush |= checkVolatileCommit();
- }
- }
- executeAndLog(new Commit(transactionId));
+ // flush whole index when volatile index has been commited.
+ if (flush) {
+ flush();
+ }
+ } finally {
+ synchronized (updateMonitor) {
+ updateInProgress = false;
+ updateMonitor.notifyAll();
+ releaseMultiReader();
+ }
+ }
+ }
- // flush whole index when volatile index has been commited.
- if (flush)
- {
- flush();
- }
- }
- finally
- {
- synchronized (updateMonitor)
- {
- updateInProgress = false;
- updateMonitor.notifyAll();
- releaseMultiReader();
- }
- }
- }
+ /**
+ * Adds a document to the index.
+ *
+ * @param doc
+ * the document to add.
+ * @throws IOException
+ * if an error occurs while adding the document to the index.
+ */
+ void addDocument(Document doc) throws IOException {
+ update(Collections.EMPTY_LIST, Arrays.asList(new Document[] { doc }));
+ }
- /**
- * Adds a document to the index.
- *
- * @param doc the document to add.
- * @throws IOException if an error occurs while adding the document to the
- * index.
- */
- void addDocument(Document doc) throws IOException
- {
- update(Collections.EMPTY_LIST, Arrays.asList(new Document[]{doc}));
- }
+ /**
+ * Deletes the first document that matches the <code>uuid</code>.
+ *
+ * @param uuid
+ * document that match this <code>uuid</code> will be deleted.
+ * @throws IOException
+ * if an error occurs while deleting the document.
+ */
+ void removeDocument(String uuid) throws IOException {
+ update(Arrays.asList(new String[] { uuid }), Collections.EMPTY_LIST);
+ }
- /**
- * Deletes the first document that matches the <code>uuid</code>.
- *
- * @param uuid document that match this <code>uuid</code> will be deleted.
- * @throws IOException if an error occurs while deleting the document.
- */
- void removeDocument(String uuid) throws IOException
- {
- update(Arrays.asList(new String[]{uuid}), Collections.EMPTY_LIST);
- }
+ /**
+ * Deletes all documents that match the <code>uuid</code>.
+ *
+ * @param uuid
+ * documents that match this <code>uuid</code> will be deleted.
+ * @return the number of deleted documents.
+ * @throws IOException
+ * if an error occurs while deleting documents.
+ */
+ synchronized int removeAllDocuments(String uuid) throws IOException {
+ synchronized (updateMonitor) {
+ updateInProgress = true;
+ }
+ int num;
+ try {
+ Term idTerm = new Term(FieldNames.UUID, uuid.toString());
+ executeAndLog(new Start(Action.INTERNAL_TRANSACTION));
+ num = volatileIndex.removeDocument(idTerm);
+ if (num > 0) {
+ redoLog.append(new DeleteNode(getTransactionId(), uuid));
+ }
+ for (int i = 0; i < indexes.size(); i++) {
+ PersistentIndex index = (PersistentIndex) indexes.get(i);
+ // only remove documents from registered indexes
+ if (indexNames.contains(index.getName())) {
+ int removed = index.removeDocument(idTerm);
+ if (removed > 0) {
+ redoLog
+ .append(new DeleteNode(getTransactionId(), uuid));
+ }
+ num += removed;
+ }
+ }
+ executeAndLog(new Commit(getTransactionId()));
+ } finally {
+ synchronized (updateMonitor) {
+ updateInProgress = false;
+ updateMonitor.notifyAll();
+ releaseMultiReader();
+ }
+ }
+ return num;
+ }
- /**
- * Deletes all documents that match the <code>uuid</code>.
- *
- * @param uuid documents that match this <code>uuid</code> will be deleted.
- * @return the number of deleted documents.
- * @throws IOException if an error occurs while deleting documents.
- */
- synchronized int removeAllDocuments(String uuid) throws IOException
- {
- synchronized (updateMonitor)
- {
- updateInProgress = true;
- }
- int num;
- try
- {
- Term idTerm = new Term(FieldNames.UUID, uuid.toString());
- executeAndLog(new Start(Action.INTERNAL_TRANSACTION));
- num = volatileIndex.removeDocument(idTerm);
- if (num > 0)
- {
- redoLog.append(new DeleteNode(getTransactionId(), uuid));
- }
- for (int i = 0; i < indexes.size(); i++)
- {
- PersistentIndex index = (PersistentIndex)indexes.get(i);
- // only remove documents from registered indexes
- if (indexNames.contains(index.getName()))
- {
- int removed = index.removeDocument(idTerm);
- if (removed > 0)
- {
- redoLog.append(new DeleteNode(getTransactionId(), uuid));
- }
- num += removed;
- }
- }
- executeAndLog(new Commit(getTransactionId()));
- }
- finally
- {
- synchronized (updateMonitor)
- {
- updateInProgress = false;
- updateMonitor.notifyAll();
- releaseMultiReader();
- }
- }
- return num;
- }
+ /**
+ * Returns <code>IndexReader</code>s for the indexes named
+ * <code>indexNames</code>. An <code>IndexListener</code> is registered and
+ * notified when documents are deleted from one of the indexes in
+ * <code>indexNames</code>.
+ * <p/>
+ * Note: the number of <code>IndexReaders</code> returned by this method is
+ * not necessarily the same as the number of index names passed. An index
+ * might have been deleted and is not reachable anymore.
+ *
+ * @param indexNames
+ * the names of the indexes for which to obtain readers.
+ * @param listener
+ * the listener to notify when documents are deleted.
+ * @return the <code>IndexReaders</code>.
+ * @throws IOException
+ * if an error occurs acquiring the index readers.
+ */
+ synchronized IndexReader[] getIndexReaders(String[] indexNames,
+ IndexListener listener) throws IOException {
+ Set names = new HashSet(Arrays.asList(indexNames));
+ Map indexReaders = new HashMap();
- /**
- * Returns <code>IndexReader</code>s for the indexes named
- * <code>indexNames</code>. An <code>IndexListener</code> is registered and
- * notified when documents are deleted from one of the indexes in
- * <code>indexNames</code>.
- * <p/>
- * Note: the number of <code>IndexReaders</code> returned by this method is
- * not necessarily the same as the number of index names passed. An index
- * might have been deleted and is not reachable anymore.
- *
- * @param indexNames the names of the indexes for which to obtain readers.
- * @param listener the listener to notify when documents are deleted.
- * @return the <code>IndexReaders</code>.
- * @throws IOException if an error occurs acquiring the index readers.
- */
- synchronized IndexReader[] getIndexReaders(String[] indexNames, IndexListener listener) throws IOException
- {
- Set names = new HashSet(Arrays.asList(indexNames));
- Map indexReaders = new HashMap();
+ try {
+ for (Iterator it = indexes.iterator(); it.hasNext();) {
+ PersistentIndex index = (PersistentIndex) it.next();
+ if (names.contains(index.getName())) {
+ indexReaders.put(index.getReadOnlyIndexReader(listener),
+ index);
+ }
+ }
+ } catch (IOException e) {
+ // release readers obtained so far
+ for (Iterator it = indexReaders.entrySet().iterator(); it.hasNext();) {
+ Map.Entry entry = (Map.Entry) it.next();
+ ReadOnlyIndexReader reader = (ReadOnlyIndexReader) entry
+ .getKey();
+ try {
+ reader.release();
+ } catch (IOException ex) {
+ log.warn("Exception releasing index reader: " + ex);
+ }
+ ((PersistentIndex) entry.getValue()).resetListener();
+ }
+ throw e;
+ }
- try
- {
- for (Iterator it = indexes.iterator(); it.hasNext();)
- {
- PersistentIndex index = (PersistentIndex)it.next();
- if (names.contains(index.getName()))
- {
- indexReaders.put(index.getReadOnlyIndexReader(listener), index);
- }
- }
- }
- catch (IOException e)
- {
- // release readers obtained so far
- for (Iterator it = indexReaders.entrySet().iterator(); it.hasNext();)
- {
- Map.Entry entry = (Map.Entry)it.next();
- ReadOnlyIndexReader reader = (ReadOnlyIndexReader)entry.getKey();
- try
- {
- reader.release();
- }
- catch (IOException ex)
- {
- log.warn("Exception releasing index reader: " + ex);
- }
- ((PersistentIndex)entry.getValue()).resetListener();
- }
- throw e;
- }
+ return (IndexReader[]) indexReaders.keySet().toArray(
+ new IndexReader[indexReaders.size()]);
+ }
- return (IndexReader[])indexReaders.keySet().toArray(new IndexReader[indexReaders.size()]);
- }
+ /**
+ * Creates a new Persistent index. The new index is not registered with this
+ * <code>MultiIndex</code>.
+ *
+ * @param indexName
+ * the name of the index to open, or <code>null</code> if an
+ * index with a new name should be created.
+ * @return a new <code>PersistentIndex</code>.
+ * @throws IOException
+ * if a new index cannot be created.
+ */
+ synchronized PersistentIndex getOrCreateIndex(String indexName)
+ throws IOException {
+ // check existing
+ for (Iterator it = indexes.iterator(); it.hasNext();) {
+ PersistentIndex idx = (PersistentIndex) it.next();
+ if (idx.getName().equals(indexName)) {
+ return idx;
+ }
+ }
- /**
- * Creates a new Persistent index. The new index is not registered with this
- * <code>MultiIndex</code>.
- *
- * @param indexName the name of the index to open, or <code>null</code> if
- * an index with a new name should be created.
- * @return a new <code>PersistentIndex</code>.
- * @throws IOException if a new index cannot be created.
- */
- synchronized PersistentIndex getOrCreateIndex(String indexName) throws IOException
- {
- // check existing
- for (Iterator it = indexes.iterator(); it.hasNext();)
- {
- PersistentIndex idx = (PersistentIndex)it.next();
- if (idx.getName().equals(indexName))
- {
- return idx;
- }
- }
+ // otherwise open / create it
+ if (indexName == null) {
+ do {
+ indexName = indexNames.newName();
+ } while (directoryManager.hasDirectory(indexName));
+ }
+ PersistentIndex index;
+ try {
+ index = new PersistentIndex(indexName, handler.getTextAnalyzer(),
+ handler.getSimilarity(), cache, indexingQueue,
+ directoryManager);
+ } catch (IOException e) {
+ // do some clean up
+ if (!directoryManager.delete(indexName)) {
+ deletable.add(indexName);
+ }
+ throw e;
+ }
+ index.setMaxFieldLength(handler.getMaxFieldLength());
+ index.setUseCompoundFile(handler.getUseCompoundFile());
+ index.setTermInfosIndexDivisor(handler.getTermInfosIndexDivisor());
- // otherwise open / create it
- if (indexName == null)
- {
- do
- {
- indexName = indexNames.newName();
- }
- while (directoryManager.hasDirectory(indexName));
- }
- PersistentIndex index;
- try
- {
- index =
- new PersistentIndex(indexName, handler.getTextAnalyzer(), handler.getSimilarity(), cache, indexingQueue,
- directoryManager);
- }
- catch (IOException e)
- {
- // do some clean up
- if (!directoryManager.delete(indexName))
- {
- deletable.add(indexName);
- }
- throw e;
- }
- index.setMaxFieldLength(handler.getMaxFieldLength());
- index.setUseCompoundFile(handler.getUseCompoundFile());
- index.setTermInfosIndexDivisor(handler.getTermInfosIndexDivisor());
+ // add to list of open indexes and return it
+ indexes.add(index);
+ return index;
+ }
- // add to list of open indexes and return it
- indexes.add(index);
- return index;
- }
+ /**
+ * Returns <code>true</code> if this multi index has an index segment with
+ * the given name. This method even returns <code>true</code> if an index
+ * segments has not yet been loaded / initialized but exists on disk.
+ *
+ * @param indexName
+ * the name of the index segment.
+ * @return <code>true</code> if it exists; otherwise <code>false</code>.
+ * @throws IOException
+ * if an error occurs while checking existence of directory.
+ */
+ synchronized boolean hasIndex(String indexName) throws IOException {
+ // check existing
+ for (Iterator it = indexes.iterator(); it.hasNext();) {
+ PersistentIndex idx = (PersistentIndex) it.next();
+ if (idx.getName().equals(indexName)) {
+ return true;
+ }
+ }
+ // check if it exists on disk
+ return directoryManager.hasDirectory(indexName);
+ }
- /**
- * Returns <code>true</code> if this multi index has an index segment with
- * the given name. This method even returns <code>true</code> if an index
- * segments has not yet been loaded / initialized but exists on disk.
- *
- * @param indexName the name of the index segment.
- * @return <code>true</code> if it exists; otherwise <code>false</code>.
- * @throws IOException if an error occurs while checking existence of
- * directory.
- */
- synchronized boolean hasIndex(String indexName) throws IOException
- {
- // check existing
- for (Iterator it = indexes.iterator(); it.hasNext();)
- {
- PersistentIndex idx = (PersistentIndex)it.next();
- if (idx.getName().equals(indexName))
- {
- return true;
- }
- }
- // check if it exists on disk
- return directoryManager.hasDirectory(indexName);
- }
+ /**
+ * Replaces the indexes with names <code>obsoleteIndexes</code> with
+ * <code>index</code>. Documents that must be deleted in <code>index</code>
+ * can be identified with <code>Term</code>s in <code>deleted</code>.
+ *
+ * @param obsoleteIndexes
+ * the names of the indexes to replace.
+ * @param index
+ * the new index that is the result of a merge of the indexes to
+ * replace.
+ * @param deleted
+ * <code>Term</code>s that identify documents that must be
+ * deleted in <code>index</code>.
+ * @throws IOException
+ * if an exception occurs while replacing the indexes.
+ */
+ void replaceIndexes(String[] obsoleteIndexes, PersistentIndex index,
+ Collection deleted) throws IOException {
- /**
- * Replaces the indexes with names <code>obsoleteIndexes</code> with
- * <code>index</code>. Documents that must be deleted in <code>index</code>
- * can be identified with <code>Term</code>s in <code>deleted</code>.
- *
- * @param obsoleteIndexes the names of the indexes to replace.
- * @param index the new index that is the result of a merge of the
- * indexes to replace.
- * @param deleted <code>Term</code>s that identify documents that must be
- * deleted in <code>index</code>.
- * @throws IOException if an exception occurs while replacing the indexes.
- */
- void replaceIndexes(String[] obsoleteIndexes, PersistentIndex index, Collection deleted) throws IOException
- {
+ if (handler.isInitializeHierarchyCache()) {
+ // force initializing of caches
+ long time = System.currentTimeMillis();
+ index.getReadOnlyIndexReader(true).release();
+ time = System.currentTimeMillis() - time;
+ log.debug("hierarchy cache initialized in {} ms", new Long(time));
+ }
- if (handler.isInitializeHierarchyCache())
- {
- // force initializing of caches
- long time = System.currentTimeMillis();
- index.getReadOnlyIndexReader(true).release();
- time = System.currentTimeMillis() - time;
- log.debug("hierarchy cache initialized in {} ms", new Long(time));
- }
+ synchronized (this) {
+ synchronized (updateMonitor) {
+ updateInProgress = true;
+ }
+ try {
+ // if we are reindexing there is already an active transaction
+ if (!reindexing) {
+ executeAndLog(new Start(Action.INTERNAL_TRANS_REPL_INDEXES));
+ }
+ // delete obsolete indexes
+ Set names = new HashSet(Arrays.asList(obsoleteIndexes));
+ for (Iterator it = names.iterator(); it.hasNext();) {
+ // do not try to delete indexes that are already gone
+ String indexName = (String) it.next();
+ if (indexNames.contains(indexName)) {
+ executeAndLog(new DeleteIndex(getTransactionId(),
+ indexName));
+ }
+ }
- synchronized (this)
- {
- synchronized (updateMonitor)
- {
- updateInProgress = true;
- }
- try
- {
- // if we are reindexing there is already an active transaction
- if (!reindexing)
- {
- executeAndLog(new Start(Action.INTERNAL_TRANS_REPL_INDEXES));
- }
- // delete obsolete indexes
- Set names = new HashSet(Arrays.asList(obsoleteIndexes));
- for (Iterator it = names.iterator(); it.hasNext();)
- {
- // do not try to delete indexes that are already gone
- String indexName = (String)it.next();
- if (indexNames.contains(indexName))
- {
- executeAndLog(new DeleteIndex(getTransactionId(), indexName));
- }
- }
+ // Index merger does not log an action when it creates the
+ // target
+ // index of the merge. We have to do this here.
+ executeAndLog(new CreateIndex(getTransactionId(), index
+ .getName()));
- // Index merger does not log an action when it creates the target
- // index of the merge. We have to do this here.
- executeAndLog(new CreateIndex(getTransactionId(), index.getName()));
+ executeAndLog(new AddIndex(getTransactionId(), index.getName()));
- executeAndLog(new AddIndex(getTransactionId(), index.getName()));
+ // delete documents in index
+ for (Iterator it = deleted.iterator(); it.hasNext();) {
+ Term id = (Term) it.next();
+ index.removeDocument(id);
+ }
+ index.commit();
- // delete documents in index
- for (Iterator it = deleted.iterator(); it.hasNext();)
- {
- Term id = (Term)it.next();
- index.removeDocument(id);
- }
- index.commit();
+ if (!reindexing) {
+ // only commit if we are not reindexing
+ // when reindexing the final commit is done at the very end
+ executeAndLog(new Commit(getTransactionId()));
+ }
+ } finally {
+ synchronized (updateMonitor) {
+ updateInProgress = false;
+ updateMonitor.notifyAll();
+ releaseMultiReader();
+ }
+ }
+ }
+ if (reindexing) {
+ // do some cleanup right away when reindexing
+ attemptDelete();
+ }
+ }
- if (!reindexing)
- {
- // only commit if we are not reindexing
- // when reindexing the final commit is done at the very end
- executeAndLog(new Commit(getTransactionId()));
- }
- }
- finally
- {
- synchronized (updateMonitor)
- {
- updateInProgress = false;
- updateMonitor.notifyAll();
- releaseMultiReader();
- }
- }
- }
- if (reindexing)
- {
- // do some cleanup right away when reindexing
- attemptDelete();
- }
- }
+ /**
+ * Returns an read-only <code>IndexReader</code> that spans alls indexes of
+ * this <code>MultiIndex</code>.
+ *
+ * @return an <code>IndexReader</code>.
+ * @throws IOException
+ * if an error occurs constructing the <code>IndexReader</code>.
+ */
+ public CachingMultiIndexReader getIndexReader() throws IOException {
+ return getIndexReader(false);
+ }
- /**
- * Returns an read-only <code>IndexReader</code> that spans alls indexes of this
- * <code>MultiIndex</code>.
- *
- * @return an <code>IndexReader</code>.
- * @throws IOException if an error occurs constructing the <code>IndexReader</code>.
- */
- public CachingMultiIndexReader getIndexReader() throws IOException
- {
- return getIndexReader(false);
- }
+ /**
+ * Returns an read-only <code>IndexReader</code> that spans alls indexes of
+ * this <code>MultiIndex</code>.
+ *
+ * @param initCache
+ * when set <code>true</code> the hierarchy cache is completely
+ * initialized before this call returns.
+ * @return an <code>IndexReader</code>.
+ * @throws IOException
+ * if an error occurs constructing the <code>IndexReader</code>.
+ */
+ public synchronized CachingMultiIndexReader getIndexReader(boolean initCache)
+ throws IOException {
+ synchronized (updateMonitor) {
+ if (multiReader != null) {
+ multiReader.acquire();
+ return multiReader;
+ }
+ // no reader available
+ // wait until no update is in progress
+ while (updateInProgress) {
+ try {
+ updateMonitor.wait();
+ } catch (InterruptedException e) {
+ throw new IOException(
+ "Interrupted while waiting to aquire reader");
+ }
+ }
+ // some other read thread might have created the reader in the
+ // meantime -> check again
+ if (multiReader == null) {
+ List readerList = new ArrayList();
+ for (int i = 0; i < indexes.size(); i++) {
+ PersistentIndex pIdx = (PersistentIndex) indexes.get(i);
+ if (indexNames.contains(pIdx.getName())) {
+ readerList.add(pIdx.getReadOnlyIndexReader(initCache));
+ }
+ }
+ readerList.add(volatileIndex.getReadOnlyIndexReader());
+ ReadOnlyIndexReader[] readers = (ReadOnlyIndexReader[]) readerList
+ .toArray(new ReadOnlyIndexReader[readerList.size()]);
+ multiReader = new CachingMultiIndexReader(readers, cache);
+ }
+ multiReader.acquire();
+ return multiReader;
+ }
+ }
- /**
- * Returns an read-only <code>IndexReader</code> that spans alls indexes of this
- * <code>MultiIndex</code>.
- *
- * @param initCache when set <code>true</code> the hierarchy cache is
- * completely initialized before this call returns.
- * @return an <code>IndexReader</code>.
- * @throws IOException if an error occurs constructing the <code>IndexReader</code>.
- */
- public synchronized CachingMultiIndexReader getIndexReader(boolean initCache) throws IOException
- {
- synchronized (updateMonitor)
- {
- if (multiReader != null)
- {
- multiReader.acquire();
- return multiReader;
- }
- // no reader available
- // wait until no update is in progress
- while (updateInProgress)
- {
- try
- {
- updateMonitor.wait();
- }
- catch (InterruptedException e)
- {
- throw new IOException("Interrupted while waiting to aquire reader");
- }
- }
- // some other read thread might have created the reader in the
- // meantime -> check again
- if (multiReader == null)
- {
- List readerList = new ArrayList();
- for (int i = 0; i < indexes.size(); i++)
- {
- PersistentIndex pIdx = (PersistentIndex)indexes.get(i);
- if (indexNames.contains(pIdx.getName()))
- {
- readerList.add(pIdx.getReadOnlyIndexReader(initCache));
- }
- }
- readerList.add(volatileIndex.getReadOnlyIndexReader());
- ReadOnlyIndexReader[] readers =
- (ReadOnlyIndexReader[])readerList.toArray(new ReadOnlyIndexReader[readerList.size()]);
- multiReader = new CachingMultiIndexReader(readers, cache);
- }
- multiReader.acquire();
- return multiReader;
- }
- }
+ /**
+ * Returns the volatile index.
+ *
+ * @return the volatile index.
+ */
+ VolatileIndex getVolatileIndex() {
+ return volatileIndex;
+ }
- /**
- * Returns the volatile index.
- *
- * @return the volatile index.
- */
- VolatileIndex getVolatileIndex()
- {
- return volatileIndex;
- }
+ /**
+ * Closes this <code>MultiIndex</code>.
+ */
+ void close() {
- /**
- * Closes this <code>MultiIndex</code>.
- */
- void close()
- {
+ // stop index merger
+ // when calling this method we must not lock this MultiIndex, otherwise
+ // a deadlock might occur
+ merger.dispose();
- // stop index merger
- // when calling this method we must not lock this MultiIndex, otherwise
- // a deadlock might occur
- merger.dispose();
+ synchronized (this) {
+ // stop timer
+ flushTask.cancel();
- synchronized (this)
- {
- // stop timer
- flushTask.cancel();
+ // commit / close indexes
+ try {
+ releaseMultiReader();
+ } catch (IOException e) {
+ log.error("Exception while closing search index.", e);
+ }
+ try {
+ flush();
+ } catch (IOException e) {
+ log.error("Exception while closing search index.", e);
+ }
+ volatileIndex.close();
+ for (int i = 0; i < indexes.size(); i++) {
+ ((PersistentIndex) indexes.get(i)).close();
+ }
- // commit / close indexes
- try
- {
- releaseMultiReader();
- }
- catch (IOException e)
- {
- log.error("Exception while closing search index.", e);
- }
- try
- {
- flush();
- }
- catch (IOException e)
- {
- log.error("Exception while closing search index.", e);
- }
- volatileIndex.close();
- for (int i = 0; i < indexes.size(); i++)
- {
- ((PersistentIndex)indexes.get(i)).close();
- }
+ // close indexing queue
+ indexingQueue.close();
- // close indexing queue
- indexingQueue.close();
+ // finally close directory
+ try {
+ indexDir.close();
+ } catch (IOException e) {
+ log.error("Exception while closing directory.", e);
+ }
+ }
+ }
- // finally close directory
- try
- {
- indexDir.close();
- }
- catch (IOException e)
- {
- log.error("Exception while closing directory.", e);
- }
- }
- }
+ /**
+ * Returns the namespace mappings of this search index.
+ *
+ * @return the namespace mappings of this search index.
+ */
+ NamespaceMappings getNamespaceMappings() {
+ return nsMappings;
+ }
- /**
- * Returns the namespace mappings of this search index.
- * @return the namespace mappings of this search index.
- */
- NamespaceMappings getNamespaceMappings()
- {
- return nsMappings;
- }
+ /**
+ * Returns the indexing queue for this multi index.
+ *
+ * @return the indexing queue for this multi index.
+ */
+ public IndexingQueue getIndexingQueue() {
+ return indexingQueue;
+ }
- /**
- * Returns the indexing queue for this multi index.
- * @return the indexing queue for this multi index.
- */
- public IndexingQueue getIndexingQueue()
- {
- return indexingQueue;
- }
+ /**
+ * Returns a lucene Document for the <code>node</code>.
+ *
+ * @param node
+ * the node to index.
+ * @return the index document.
+ * @throws RepositoryException
+ * if an error occurs while reading from the workspace.
+ */
+ Document createDocument(NodeData node) throws RepositoryException {
+ return handler.createDocument(node, nsMappings, version);
+ }
- /**
- * Returns a lucene Document for the <code>node</code>.
- *
- * @param node the node to index.
- * @return the index document.
- * @throws RepositoryException if an error occurs while reading from the
- * workspace.
- */
- Document createDocument(NodeData node) throws RepositoryException
- {
- return handler.createDocument(node, nsMappings, version);
- }
+ /**
+ * Returns a lucene Document for the Node with <code>id</code>.
+ *
+ * @param id
+ * the id of the node to index.
+ * @return the index document.
+ * @throws RepositoryException
+ * if an error occurs while reading from the workspace or if
+ * there is no node with <code>id</code>.
+ */
+ Document createDocument(String id) throws RepositoryException {
+ ItemData data = handler.getContext().getItemStateManager().getItemData(
+ id);
+ if (data == null)
+ throw new ItemNotFoundException("Item id=" + id + " not found");
+ if (!data.isNode())
+ throw new RepositoryException("Item with id " + id
+ + " is not a node");
+ return createDocument((NodeData) data);
- /**
- * Returns a lucene Document for the Node with <code>id</code>.
- *
- * @param id the id of the node to index.
- * @return the index document.
- * @throws RepositoryException if an error occurs while reading from the
- * workspace or if there is no node with
- * <code>id</code>.
- */
- Document createDocument(String id) throws RepositoryException
- {
- ItemData data = handler.getContext().getItemStateManager().getItemData(id);
- if (data == null)
- throw new ItemNotFoundException("Item id=" + id + " not found");
- if (!data.isNode())
- throw new RepositoryException("Item with id " + id + " is not a node");
- return createDocument((NodeData)data);
+ }
- }
+ /**
+ * Returns <code>true</code> if the redo log contained entries while this
+ * index was instantiated; <code>false</code> otherwise.
+ *
+ * @return <code>true</code> if the redo log contained entries.
+ */
+ boolean getRedoLogApplied() {
+ return redoLogApplied;
+ }
- /**
- * Returns <code>true</code> if the redo log contained entries while
- * this index was instantiated; <code>false</code> otherwise.
- * @return <code>true</code> if the redo log contained entries.
- */
- boolean getRedoLogApplied()
- {
- return redoLogApplied;
- }
+ /**
+ * Removes the <code>index</code> from the list of active sub indexes. The
+ * Index is not acutally deleted right away, but postponed to the
+ * transaction commit.
+ * <p/>
+ * This method does not close the index, but rather expects that the index
+ * has already been closed.
+ *
+ * @param index
+ * the index to delete.
+ */
+ synchronized void deleteIndex(PersistentIndex index) {
+ // remove it from the lists if index is registered
+ indexes.remove(index);
+ indexNames.removeName(index.getName());
+ synchronized (deletable) {
+ log.debug("Moved " + index.getName() + " to deletable");
+ deletable.add(index.getName());
+ }
+ }
- /**
- * Removes the <code>index</code> from the list of active sub indexes. The
- * Index is not acutally deleted right away, but postponed to the transaction
- * commit.
- * <p/>
- * This method does not close the index, but rather expects that the index
- * has already been closed.
- *
- * @param index the index to delete.
- */
- synchronized void deleteIndex(PersistentIndex index)
- {
- // remove it from the lists if index is registered
- indexes.remove(index);
- indexNames.removeName(index.getName());
- synchronized (deletable)
- {
- log.debug("Moved " + index.getName() + " to deletable");
- deletable.add(index.getName());
- }
- }
+ /**
+ * Flushes this <code>MultiIndex</code>. Persists all pending changes and
+ * resets the redo log.
+ *
+ * @throws IOException
+ * if the flush fails.
+ */
+ public void flush() throws IOException {
+ synchronized (this) {
+ // commit volatile index
+ executeAndLog(new Start(Action.INTERNAL_TRANSACTION));
+ commitVolatileIndex();
- /**
- * Flushes this <code>MultiIndex</code>. Persists all pending changes and
- * resets the redo log.
- *
- * @throws IOException if the flush fails.
- */
- public void flush() throws IOException
- {
- synchronized (this)
- {
- // commit volatile index
- executeAndLog(new Start(Action.INTERNAL_TRANSACTION));
- commitVolatileIndex();
+ // commit persistent indexes
+ for (int i = indexes.size() - 1; i >= 0; i--) {
+ PersistentIndex index = (PersistentIndex) indexes.get(i);
+ // only commit indexes we own
+ // index merger also places PersistentIndex instances in
+ // indexes,
+ // but does not make them public by registering the name in
+ // indexNames
+ if (indexNames.contains(index.getName())) {
+ index.commit();
+ // check if index still contains documents
+ if (index.getNumDocuments() == 0) {
+ executeAndLog(new DeleteIndex(getTransactionId(), index
+ .getName()));
+ }
+ }
+ }
+ executeAndLog(new Commit(getTransactionId()));
- // commit persistent indexes
- for (int i = indexes.size() - 1; i >= 0; i--)
- {
- PersistentIndex index = (PersistentIndex)indexes.get(i);
- // only commit indexes we own
- // index merger also places PersistentIndex instances in indexes,
- // but does not make them public by registering the name in indexNames
- if (indexNames.contains(index.getName()))
- {
- index.commit();
- // check if index still contains documents
- if (index.getNumDocuments() == 0)
- {
- executeAndLog(new DeleteIndex(getTransactionId(), index.getName()));
- }
- }
- }
- executeAndLog(new Commit(getTransactionId()));
+ indexNames.write(indexDir);
- indexNames.write(indexDir);
+ // reset redo log
+ redoLog.clear();
- // reset redo log
- redoLog.clear();
+ lastFlushTime = System.currentTimeMillis();
+ }
- lastFlushTime = System.currentTimeMillis();
- }
+ // delete obsolete indexes
+ attemptDelete();
+ }
- // delete obsolete indexes
- attemptDelete();
- }
+ /**
+ * Releases the {@link #multiReader} and sets it <code>null</code>. If the
+ * reader is already <code>null</code> this method does nothing. When this
+ * method returns {@link #multiReader} is guaranteed to be <code>null</code>
+ * even if an exception is thrown.
+ * <p/>
+ * Please note that this method does not take care of any synchronization. A
+ * caller must ensure that it is the only thread operating on this multi
+ * index, or that it holds the {@link #updateMonitor}.
+ *
+ * @throws IOException
+ * if an error occurs while releasing the reader.
+ */
+ void releaseMultiReader() throws IOException {
+ if (multiReader != null) {
+ try {
+ multiReader.release();
+ } finally {
+ multiReader = null;
+ }
+ }
+ }
- /**
- * Releases the {@link #multiReader} and sets it <code>null</code>. If the
- * reader is already <code>null</code> this method does nothing. When this
- * method returns {@link #multiReader} is guaranteed to be <code>null</code>
- * even if an exception is thrown.
- * <p/>
- * Please note that this method does not take care of any synchronization.
- * A caller must ensure that it is the only thread operating on this multi
- * index, or that it holds the {@link #updateMonitor}.
- *
- * @throws IOException if an error occurs while releasing the reader.
- */
- void releaseMultiReader() throws IOException
- {
- if (multiReader != null)
- {
- try
- {
- multiReader.release();
- }
- finally
- {
- multiReader = null;
- }
- }
- }
+ // -------------------------< internal
+ // >-------------------------------------
- //-------------------------< internal >-------------------------------------
+ /**
+ * Enqueues unused segments for deletion in {@link #deletable}. This method
+ * does not synchronize on {@link #deletable}! A caller must ensure that it
+ * is the only one acting on the {@link #deletable} map.
+ *
+ * @throws IOException
+ * if an error occurs while reading directories.
+ */
+ private void enqueueUnusedSegments() throws IOException {
+ // walk through index segments
+ String[] dirNames = directoryManager.getDirectoryNames();
+ for (int i = 0; i < dirNames.length; i++) {
+ if (dirNames[i].startsWith("_")
+ && !indexNames.contains(dirNames[i])) {
+ deletable.add(dirNames[i]);
+ }
+ }
+ }
- /**
- * Enqueues unused segments for deletion in {@link #deletable}. This method
- * does not synchronize on {@link #deletable}! A caller must ensure that it
- * is the only one acting on the {@link #deletable} map.
- *
- * @throws IOException if an error occurs while reading directories.
- */
- private void enqueueUnusedSegments() throws IOException
- {
- // walk through index segments
- String[] dirNames = directoryManager.getDirectoryNames();
- for (int i = 0; i < dirNames.length; i++)
- {
- if (dirNames[i].startsWith("_") && !indexNames.contains(dirNames[i]))
- {
- deletable.add(dirNames[i]);
- }
- }
- }
+ private void scheduleFlushTask() {
+ lastFlushTime = System.currentTimeMillis();
+ FLUSH_TIMER.schedule(flushTask, 0, 1000);
+ }
- private void scheduleFlushTask()
- {
- lastFlushTime = System.currentTimeMillis();
- FLUSH_TIMER.schedule(flushTask, 0, 1000);
- }
+ /**
+ * Resets the volatile index to a new instance.
+ */
+ private void resetVolatileIndex() throws IOException {
+ volatileIndex = new VolatileIndex(handler.getTextAnalyzer(), handler
+ .getSimilarity(), indexingQueue);
+ volatileIndex.setUseCompoundFile(handler.getUseCompoundFile());
+ volatileIndex.setMaxFieldLength(handler.getMaxFieldLength());
+ volatileIndex.setBufferSize(handler.getBufferSize());
+ }
- /**
- * Resets the volatile index to a new instance.
- */
- private void resetVolatileIndex() throws IOException
- {
- volatileIndex = new VolatileIndex(handler.getTextAnalyzer(), handler.getSimilarity(), indexingQueue);
- volatileIndex.setUseCompoundFile(handler.getUseCompoundFile());
- volatileIndex.setMaxFieldLength(handler.getMaxFieldLength());
- volatileIndex.setBufferSize(handler.getBufferSize());
- }
+ /**
+ * Returns the current transaction id.
+ *
+ * @return the current transaction id.
+ */
+ private long getTransactionId() {
+ return currentTransactionId;
+ }
- /**
- * Returns the current transaction id.
- *
- * @return the current transaction id.
- */
- private long getTransactionId()
- {
- return currentTransactionId;
- }
+ /**
+ * Executes action <code>a</code> and appends the action to the redo log if
+ * successful.
+ *
+ * @param a
+ * the <code>Action</code> to execute.
+ * @return the executed action.
+ * @throws IOException
+ * if an error occurs while executing the action or appending
+ * the action to the redo log.
+ */
+ private Action executeAndLog(Action a) throws IOException {
+ a.execute(this);
+ redoLog.append(a);
+ // please note that flushing the redo log is only required on
+ // commit, but we also want to keep track of new indexes for sure.
+ // otherwise it might happen that unused index folders are orphaned
+ // after a crash.
+ if (a.getType() == Action.TYPE_COMMIT
+ || a.getType() == Action.TYPE_ADD_INDEX) {
+ redoLog.flush();
+ }
+ return a;
+ }
- /**
- * Executes action <code>a</code> and appends the action to the redo log if
- * successful.
- *
- * @param a the <code>Action</code> to execute.
- * @return the executed action.
- * @throws IOException if an error occurs while executing the action
- * or appending the action to the redo log.
- */
- private Action executeAndLog(Action a) throws IOException
- {
- a.execute(this);
- redoLog.append(a);
- // please note that flushing the redo log is only required on
- // commit, but we also want to keep track of new indexes for sure.
- // otherwise it might happen that unused index folders are orphaned
- // after a crash.
- if (a.getType() == Action.TYPE_COMMIT || a.getType() == Action.TYPE_ADD_INDEX)
- {
- redoLog.flush();
- }
- return a;
- }
+ /**
+ * Checks if it is needed to commit the volatile index according to
+ * {@link SearchIndex#getMaxVolatileIndexSize()}.
+ *
+ * @return <code>true</code> if the volatile index has been committed,
+ * <code>false</code> otherwise.
+ * @throws IOException
+ * if an error occurs while committing the volatile index.
+ */
+ private boolean checkVolatileCommit() throws IOException {
+ if (volatileIndex.getRamSizeInBytes() >= handler
+ .getMaxVolatileIndexSize()) {
+ commitVolatileIndex();
+ return true;
+ }
+ return false;
+ }
- /**
- * Checks if it is needed to commit the volatile index according to {@link
- * SearchIndex#getMaxVolatileIndexSize()}.
- *
- * @return <code>true</code> if the volatile index has been committed,
- * <code>false</code> otherwise.
- * @throws IOException if an error occurs while committing the volatile
- * index.
- */
- private boolean checkVolatileCommit() throws IOException
- {
- if (volatileIndex.getRamSizeInBytes() >= handler.getMaxVolatileIndexSize())
- {
- commitVolatileIndex();
- return true;
- }
- return false;
- }
+ /**
+ * Commits the volatile index to a persistent index. The new persistent
+ * index is added to the list of indexes but not written to disk. When this
+ * method returns a new volatile index has been created.
+ *
+ * @throws IOException
+ * if an error occurs while writing the volatile index to disk.
+ */
+ private void commitVolatileIndex() throws IOException {
- /**
- * Commits the volatile index to a persistent index. The new persistent
- * index is added to the list of indexes but not written to disk. When this
- * method returns a new volatile index has been created.
- *
- * @throws IOException if an error occurs while writing the volatile index
- * to disk.
- */
- private void commitVolatileIndex() throws IOException
- {
+ // check if volatile index contains documents at all
+ if (volatileIndex.getNumDocuments() > 0) {
- // check if volatile index contains documents at all
- if (volatileIndex.getNumDocuments() > 0)
- {
+ long time = System.currentTimeMillis();
+ // create index
+ CreateIndex create = new CreateIndex(getTransactionId(), null);
+ executeAndLog(create);
- long time = System.currentTimeMillis();
- // create index
- CreateIndex create = new CreateIndex(getTransactionId(), null);
- executeAndLog(create);
+ // commit volatile index
+ executeAndLog(new VolatileCommit(getTransactionId(), create
+ .getIndexName()));
- // commit volatile index
- executeAndLog(new VolatileCommit(getTransactionId(), create.getIndexName()));
+ // add new index
+ AddIndex add = new AddIndex(getTransactionId(), create
+ .getIndexName());
+ executeAndLog(add);
- // add new index
- AddIndex add = new AddIndex(getTransactionId(), create.getIndexName());
- executeAndLog(add);
+ // create new volatile index
+ resetVolatileIndex();
- // create new volatile index
- resetVolatileIndex();
+ time = System.currentTimeMillis() - time;
+ log.debug("Committed in-memory index in " + time + "ms.");
+ }
+ }
- time = System.currentTimeMillis() - time;
- log.debug("Committed in-memory index in " + time + "ms.");
- }
- }
+ /**
+ * Recursively creates an index starting with the NodeState
+ * <code>node</code>.
+ *
+ * @param node
+ * the current NodeState.
+ * @param path
+ * the path of the current node.
+ * @param stateMgr
+ * the shared item state manager.
+ * @param count
+ * the number of nodes already indexed.
+ * @return the number of nodes indexed so far.
+ * @throws IOException
+ * if an error occurs while writing to the index.
+ * @throws ItemStateException
+ * if an node state cannot be found.
+ * @throws RepositoryException
+ * if any other error occurs
+ */
+ private long createIndex(NodeData node, ItemDataConsumer stateMgr,
+ long count) throws IOException, RepositoryException {
+ // NodeId id = node.getNodeId();
- /**
- * Recursively creates an index starting with the NodeState
- * <code>node</code>.
- *
- * @param node the current NodeState.
- * @param path the path of the current node.
- * @param stateMgr the shared item state manager.
- * @param count the number of nodes already indexed.
- * @return the number of nodes indexed so far.
- * @throws IOException if an error occurs while writing to the
- * index.
- * @throws ItemStateException if an node state cannot be found.
- * @throws RepositoryException if any other error occurs
- */
- private long createIndex(NodeData node, ItemDataConsumer stateMgr, long count) throws IOException,
- RepositoryException
- {
- //NodeId id = node.getNodeId();
- if (excludedIDs.contains(node.getIdentifier()))
- {
- return count;
- }
- executeAndLog(new AddNode(getTransactionId(), node.getIdentifier()));
- if (++count % 100 == 0)
- {
+ if (indexingTree.isExcluded(node)) {
+ return count;
+ }
+ executeAndLog(new AddNode(getTransactionId(), node.getIdentifier()));
+ if (++count % 100 == 0) {
- log.info("indexing... {} ({})", node.getQPath().getAsString(), new Long(count));
- }
- if (count % 10 == 0)
- {
- checkIndexingQueue(true);
- }
- checkVolatileCommit();
- List<NodeData> children = stateMgr.getChildNodesData(node);
- for (NodeData nodeData : children)
- {
+ log.info("indexing... {} ({})", node.getQPath().getAsString(),
+ new Long(count));
+ }
+ if (count % 10 == 0) {
+ checkIndexingQueue(true);
+ }
+ checkVolatileCommit();
+ List<NodeData> children = stateMgr.getChildNodesData(node);
+ for (NodeData nodeData : children) {
- NodeData childState = (NodeData)stateMgr.getItemData(nodeData.getIdentifier());
- if (childState == null)
- {
- handler.getOnWorkspaceInconsistencyHandler().handleMissingChildNode(new ItemNotFoundException("Child not found "), handler, nodeData.getQPath(), node, nodeData);
- }
+ NodeData childState = (NodeData) stateMgr.getItemData(nodeData
+ .getIdentifier());
+ if (childState == null) {
+ handler.getOnWorkspaceInconsistencyHandler()
+ .handleMissingChildNode(
+ new ItemNotFoundException("Child not found "),
+ handler, nodeData.getQPath(), node, nodeData);
+ }
- if (nodeData != null)
- {
- count = createIndex(nodeData, stateMgr, count);
- }
- }
+ if (nodeData != null) {
+ count = createIndex(nodeData, stateMgr, count);
+ }
+ }
- return count;
- }
+ return count;
+ }
- /**
- * Attempts to delete all files recorded in {@link #deletable}.
- */
- private void attemptDelete()
- {
- synchronized (deletable)
- {
- for (Iterator it = deletable.iterator(); it.hasNext();)
- {
- String indexName = (String)it.next();
- if (directoryManager.delete(indexName))
- {
- it.remove();
- }
- else
- {
- log.info("Unable to delete obsolete index: " + indexName);
- }
- }
- }
- }
+ /**
+ * Attempts to delete all files recorded in {@link #deletable}.
+ */
+ private void attemptDelete() {
+ synchronized (deletable) {
+ for (Iterator it = deletable.iterator(); it.hasNext();) {
+ String indexName = (String) it.next();
+ if (directoryManager.delete(indexName)) {
+ it.remove();
+ } else {
+ log.info("Unable to delete obsolete index: " + indexName);
+ }
+ }
+ }
+ }
- /**
- * Removes the deletable file if it exists. The file is not used anymore
- * in Jackrabbit versions >= 1.5.
- */
- private void removeDeletable()
- {
- String fileName = "deletable";
- try
- {
- if (indexDir.fileExists(fileName))
- {
- indexDir.deleteFile(fileName);
- }
- }
- catch (IOException e)
- {
- log.warn("Unable to remove file 'deletable'.", e);
- }
- }
+ /**
+ * Removes the deletable file if it exists. The file is not used anymore in
+ * Jackrabbit versions >= 1.5.
+ */
+ private void removeDeletable() {
+ String fileName = "deletable";
+ try {
+ if (indexDir.fileExists(fileName)) {
+ indexDir.deleteFile(fileName);
+ }
+ } catch (IOException e) {
+ log.warn("Unable to remove file 'deletable'.", e);
+ }
+ }
- /**
- * Checks the duration between the last commit to this index and the
- * current time and flushes the index (if there are changes at all)
- * if the duration (idle time) is more than {@link SearchIndex#getVolatileIdleTime()}
- * seconds.
- */
- private synchronized void checkFlush()
- {
- long idleTime = System.currentTimeMillis() - lastFlushTime;
- // do not flush if volatileIdleTime is zero or negative
- if (handler.getVolatileIdleTime() > 0 && idleTime > handler.getVolatileIdleTime() * 1000)
- {
- try
- {
- if (redoLog.hasEntries())
- {
- log.debug("Flushing index after being idle for " + idleTime + " ms.");
- synchronized (updateMonitor)
- {
- updateInProgress = true;
- }
- try
- {
- flush();
- }
- finally
- {
- synchronized (updateMonitor)
- {
- updateInProgress = false;
- updateMonitor.notifyAll();
- releaseMultiReader();
- }
- }
- }
- }
- catch (IOException e)
- {
- log.error("Unable to commit volatile index", e);
- }
- }
- }
+ /**
+ * Checks the duration between the last commit to this index and the current
+ * time and flushes the index (if there are changes at all) if the duration
+ * (idle time) is more than {@link SearchIndex#getVolatileIdleTime()}
+ * seconds.
+ */
+ private synchronized void checkFlush() {
+ long idleTime = System.currentTimeMillis() - lastFlushTime;
+ // do not flush if volatileIdleTime is zero or negative
+ if (handler.getVolatileIdleTime() > 0
+ && idleTime > handler.getVolatileIdleTime() * 1000) {
+ try {
+ if (redoLog.hasEntries()) {
+ log.debug("Flushing index after being idle for " + idleTime
+ + " ms.");
+ synchronized (updateMonitor) {
+ updateInProgress = true;
+ }
+ try {
+ flush();
+ } finally {
+ synchronized (updateMonitor) {
+ updateInProgress = false;
+ updateMonitor.notifyAll();
+ releaseMultiReader();
+ }
+ }
+ }
+ } catch (IOException e) {
+ log.error("Unable to commit volatile index", e);
+ }
+ }
+ }
- /**
- * Checks the indexing queue for finished text extrator jobs and updates the
- * index accordingly if there are any new ones. This method is synchronized
- * and should only be called by the timer task that periodically checks if
- * there are documents ready in the indexing queue. A new transaction is
- * used when documents are transfered from the indexing queue to the index.
- */
- private synchronized void checkIndexingQueue()
- {
- checkIndexingQueue(false);
- }
+ /**
+ * Checks the indexing queue for finished text extrator jobs and updates the
+ * index accordingly if there are any new ones. This method is synchronized
+ * and should only be called by the timer task that periodically checks if
+ * there are documents ready in the indexing queue. A new transaction is
+ * used when documents are transfered from the indexing queue to the index.
+ */
+ private synchronized void checkIndexingQueue() {
+ checkIndexingQueue(false);
+ }
- /**
- * Checks the indexing queue for finished text extrator jobs and updates the
- * index accordingly if there are any new ones.
- *
- * @param transactionPresent whether a transaction is in progress and the
- * current {@link #getTransactionId()} should be
- * used. If <code>false</code> a new transaction
- * is created when documents are transfered from
- * the indexing queue to the index.
- */
- private void checkIndexingQueue(boolean transactionPresent)
- {
- Document[] docs = indexingQueue.getFinishedDocuments();
- Map finished = new HashMap();
- for (int i = 0; i < docs.length; i++)
- {
- String uuid = docs[i].get(FieldNames.UUID);
- finished.put(uuid, docs[i]);
- }
+ /**
+ * Checks the indexing queue for finished text extrator jobs and updates the
+ * index accordingly if there are any new ones.
+ *
+ * @param transactionPresent
+ * whether a transaction is in progress and the current
+ * {@link #getTransactionId()} should be used. If
+ * <code>false</code> a new transaction is created when documents
+ * are transfered from the indexing queue to the index.
+ */
+ private void checkIndexingQueue(boolean transactionPresent) {
+ Document[] docs = indexingQueue.getFinishedDocuments();
+ Map finished = new HashMap();
+ for (int i = 0; i < docs.length; i++) {
+ String uuid = docs[i].get(FieldNames.UUID);
+ finished.put(uuid, docs[i]);
+ }
- // now update index with the remaining ones if there are any
- if (!finished.isEmpty())
- {
- log.info("updating index with {} nodes from indexing queue.", new Long(finished.size()));
+ // now update index with the remaining ones if there are any
+ if (!finished.isEmpty()) {
+ log.info("updating index with {} nodes from indexing queue.",
+ new Long(finished.size()));
- // remove documents from the queue
- for (Iterator it = finished.keySet().iterator(); it.hasNext();)
- {
- indexingQueue.removeDocument(it.next().toString());
- }
+ // remove documents from the queue
+ for (Iterator it = finished.keySet().iterator(); it.hasNext();) {
+ indexingQueue.removeDocument(it.next().toString());
+ }
- try
- {
- if (transactionPresent)
- {
- for (Iterator it = finished.keySet().iterator(); it.hasNext();)
- {
- executeAndLog(new DeleteNode(getTransactionId(), (String)it.next()));
- }
- for (Iterator it = finished.values().iterator(); it.hasNext();)
- {
- executeAndLog(new AddNode(getTransactionId(), (Document)it.next()));
- }
- }
- else
- {
- update(finished.keySet(), finished.values());
- }
- }
- catch (IOException e)
- {
- // update failed
- log.warn("Failed to update index with deferred text extraction", e);
- }
- }
- }
+ try {
+ if (transactionPresent) {
+ for (Iterator it = finished.keySet().iterator(); it
+ .hasNext();) {
+ executeAndLog(new DeleteNode(getTransactionId(),
+ (String) it.next()));
+ }
+ for (Iterator it = finished.values().iterator(); it
+ .hasNext();) {
+ executeAndLog(new AddNode(getTransactionId(),
+ (Document) it.next()));
+ }
+ } else {
+ update(finished.keySet(), finished.values());
+ }
+ } catch (IOException e) {
+ // update failed
+ log.warn(
+ "Failed to update index with deferred text extraction",
+ e);
+ }
+ }
+ }
- //------------------------< Actions >---------------------------------------
+ // ------------------------< Actions
+ // >---------------------------------------
- /**
- * Defines an action on an <code>MultiIndex</code>.
- */
- public abstract static class Action
- {
+ /**
+ * Defines an action on an <code>MultiIndex</code>.
+ */
+ public abstract static class Action {
- /**
- * Action identifier in redo log for transaction start action.
- */
- static final String START = "STR";
+ /**
+ * Action identifier in redo log for transaction start action.
+ */
+ static final String START = "STR";
- /**
- * Action type for start action.
- */
- public static final int TYPE_START = 0;
+ /**
+ * Action type for start action.
+ */
+ public static final int TYPE_START = 0;
- /**
- * Action identifier in redo log for add node action.
- */
- static final String ADD_NODE = "ADD";
+ /**
+ * Action identifier in redo log for add node action.
+ */
+ static final String ADD_NODE = "ADD";
- /**
- * Action type for add node action.
- */
- public static final int TYPE_ADD_NODE = 1;
+ /**
+ * Action type for add node action.
+ */
+ public static final int TYPE_ADD_NODE = 1;
- /**
- * Action identifier in redo log for node delete action.
- */
- static final String DELETE_NODE = "DEL";
+ /**
+ * Action identifier in redo log for node delete action.
+ */
+ static final String DELETE_NODE = "DEL";
- /**
- * Action type for delete node action.
- */
- public static final int TYPE_DELETE_NODE = 2;
+ /**
+ * Action type for delete node action.
+ */
+ public static final int TYPE_DELETE_NODE = 2;
- /**
- * Action identifier in redo log for transaction commit action.
- */
- static final String COMMIT = "COM";
+ /**
+ * Action identifier in redo log for transaction commit action.
+ */
+ static final String COMMIT = "COM";
- /**
- * Action type for commit action.
- */
- public static final int TYPE_COMMIT = 3;
+ /**
+ * Action type for commit action.
+ */
+ public static final int TYPE_COMMIT = 3;
- /**
- * Action identifier in redo log for volatile index commit action.
- */
- static final String VOLATILE_COMMIT = "VOL_COM";
+ /**
+ * Action identifier in redo log for volatile index commit action.
+ */
+ static final String VOLATILE_COMMIT = "VOL_COM";
- /**
- * Action type for volatile index commit action.
- */
- public static final int TYPE_VOLATILE_COMMIT = 4;
+ /**
+ * Action type for volatile index commit action.
+ */
+ public static final int TYPE_VOLATILE_COMMIT = 4;
- /**
- * Action identifier in redo log for index create action.
- */
- static final String CREATE_INDEX = "CRE_IDX";
+ /**
+ * Action identifier in redo log for index create action.
+ */
+ static final String CREATE_INDEX = "CRE_IDX";
- /**
- * Action type for create index action.
- */
- public static final int TYPE_CREATE_INDEX = 5;
+ /**
+ * Action type for create index action.
+ */
+ public static final int TYPE_CREATE_INDEX = 5;
- /**
- * Action identifier in redo log for index add action.
- */
- static final String ADD_INDEX = "ADD_IDX";
+ /**
+ * Action identifier in redo log for index add action.
+ */
+ static final String ADD_INDEX = "ADD_IDX";
- /**
- * Action type for add index action.
- */
- public static final int TYPE_ADD_INDEX = 6;
+ /**
+ * Action type for add index action.
+ */
+ public static final int TYPE_ADD_INDEX = 6;
- /**
- * Action identifier in redo log for delete index action.
- */
- static final String DELETE_INDEX = "DEL_IDX";
+ /**
+ * Action identifier in redo log for delete index action.
+ */
+ static final String DELETE_INDEX = "DEL_IDX";
- /**
- * Action type for delete index action.
- */
- public static final int TYPE_DELETE_INDEX = 7;
+ /**
+ * Action type for delete index action.
+ */
+ public static final int TYPE_DELETE_INDEX = 7;
- /**
- * Transaction identifier for internal actions like volatile index
- * commit triggered by timer thread.
- */
- static final long INTERNAL_TRANSACTION = -1;
+ /**
+ * Transaction identifier for internal actions like volatile index
+ * commit triggered by timer thread.
+ */
+ static final long INTERNAL_TRANSACTION = -1;
- /**
- * Transaction identifier for internal action that replaces indexs.
- */
- static final long INTERNAL_TRANS_REPL_INDEXES = -2;
+ /**
+ * Transaction identifier for internal action that replaces indexs.
+ */
+ static final long INTERNAL_TRANS_REPL_INDEXES = -2;
- /**
- * The id of the transaction that executed this action.
- */
- private final long transactionId;
+ /**
+ * The id of the transaction that executed this action.
+ */
+ private final long transactionId;
- /**
- * The action type.
- */
- private final int type;
+ /**
+ * The action type.
+ */
+ private final int type;
- /**
- * Creates a new <code>Action</code>.
- *
- * @param transactionId the id of the transaction that executed this
- * action.
- * @param type the action type.
- */
- Action(long transactionId, int type)
- {
- this.transactionId = transactionId;
- this.type = type;
- }
+ /**
+ * Creates a new <code>Action</code>.
+ *
+ * @param transactionId
+ * the id of the transaction that executed this action.
+ * @param type
+ * the action type.
+ */
+ Action(long transactionId, int type) {
+ this.transactionId = transactionId;
+ this.type = type;
+ }
- /**
- * Returns the transaction id for this <code>Action</code>.
- *
- * @return the transaction id for this <code>Action</code>.
- */
- long getTransactionId()
- {
- return transactionId;
- }
+ /**
+ * Returns the transaction id for this <code>Action</code>.
+ *
+ * @return the transaction id for this <code>Action</code>.
+ */
+ long getTransactionId() {
+ return transactionId;
+ }
- /**
- * Returns the action type.
- *
- * @return the action type.
- */
- int getType()
- {
- return type;
- }
+ /**
+ * Returns the action type.
+ *
+ * @return the action type.
+ */
+ int getType() {
+ return type;
+ }
- /**
- * Executes this action on the <code>index</code>.
- *
- * @param index the index where to execute the action.
- * @throws IOException if the action fails due to some I/O error in
- * the index or some other error.
- */
- public abstract void execute(MultiIndex index) throws IOException;
+ /**
+ * Executes this action on the <code>index</code>.
+ *
+ * @param index
+ * the index where to execute the action.
+ * @throws IOException
+ * if the action fails due to some I/O error in the index or
+ * some other error.
+ */
+ public abstract void execute(MultiIndex index) throws IOException;
- /**
- * Executes the inverse operation of this action. That is, does an undo
- * of this action. This default implementation does nothing, but returns
- * silently.
- *
- * @param index the index where to undo the action.
- * @throws IOException if the action cannot be undone.
- */
- public void undo(MultiIndex index) throws IOException
- {
- }
+ /**
+ * Executes the inverse operation of this action. That is, does an undo
+ * of this action. This default implementation does nothing, but returns
+ * silently.
+ *
+ * @param index
+ * the index where to undo the action.
+ * @throws IOException
+ * if the action cannot be undone.
+ */
+ public void undo(MultiIndex index) throws IOException {
+ }
- /**
- * Returns a <code>String</code> representation of this action that can be
- * written to the {@link RedoLog}.
- *
- * @return a <code>String</code> representation of this action.
- */
- public abstract String toString();
+ /**
+ * Returns a <code>String</code> representation of this action that can
+ * be written to the {@link RedoLog}.
+ *
+ * @return a <code>String</code> representation of this action.
+ */
+ public abstract String toString();
- /**
- * Parses an line in the redo log and created an {@link Action}.
- *
- * @param line the line from the redo log.
- * @return an <code>Action</code>.
- * @throws IllegalArgumentException if the line is malformed.
- */
- static Action fromString(String line) throws IllegalArgumentException
- {
- int endTransIdx = line.indexOf(' ');
- if (endTransIdx == -1)
- {
- throw new IllegalArgumentException(line);
- }
- long transactionId;
- try
- {
- transactionId = Long.parseLong(line.substring(0, endTransIdx));
- }
- catch (NumberFormatException e)
- {
- throw new IllegalArgumentException(line);
- }
- int endActionIdx = line.indexOf(' ', endTransIdx + 1);
- if (endActionIdx == -1)
- {
- // action does not have arguments
- endActionIdx = line.length();
- }
- String actionLabel = line.substring(endTransIdx + 1, endActionIdx);
- String arguments = "";
- if (endActionIdx + 1 <= line.length())
- {
- arguments = line.substring(endActionIdx + 1);
- }
- Action a;
- if (actionLabel.equals(Action.ADD_NODE))
- {
- a = AddNode.fromString(transactionId, arguments);
- }
- else if (actionLabel.equals(Action.ADD_INDEX))
- {
- a = AddIndex.fromString(transactionId, arguments);
- }
- else if (actionLabel.equals(Action.COMMIT))
- {
- a = Commit.fromString(transactionId, arguments);
- }
- else if (actionLabel.equals(Action.CREATE_INDEX))
- {
- a = CreateIndex.fromString(transactionId, arguments);
- }
- else if (actionLabel.equals(Action.DELETE_INDEX))
- {
- a = DeleteIndex.fromString(transactionId, arguments);
- }
- else if (actionLabel.equals(Action.DELETE_NODE))
- {
- a = DeleteNode.fromString(transactionId, arguments);
- }
- else if (actionLabel.equals(Action.START))
- {
- a = Start.fromString(transactionId, arguments);
- }
- else if (actionLabel.equals(Action.VOLATILE_COMMIT))
- {
- a = VolatileCommit.fromString(transactionId, arguments);
- }
- else
- {
- throw new IllegalArgumentException(line);
- }
- return a;
- }
- }
+ /**
+ * Parses an line in the redo log and created an {@link Action}.
+ *
+ * @param line
+ * the line from the redo log.
+ * @return an <code>Action</code>.
+ * @throws IllegalArgumentException
+ * if the line is malformed.
+ */
+ static Action fromString(String line) throws IllegalArgumentException {
+ int endTransIdx = line.indexOf(' ');
+ if (endTransIdx == -1) {
+ throw new IllegalArgumentException(line);
+ }
+ long transactionId;
+ try {
+ transactionId = Long.parseLong(line.substring(0, endTransIdx));
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException(line);
+ }
+ int endActionIdx = line.indexOf(' ', endTransIdx + 1);
+ if (endActionIdx == -1) {
+ // action does not have arguments
+ endActionIdx = line.length();
+ }
+ String actionLabel = line.substring(endTransIdx + 1, endActionIdx);
+ String arguments = "";
+ if (endActionIdx + 1 <= line.length()) {
+ arguments = line.substring(endActionIdx + 1);
+ }
+ Action a;
+ if (actionLabel.equals(Action.ADD_NODE)) {
+ a = AddNode.fromString(transactionId, arguments);
+ } else if (actionLabel.equals(Action.ADD_INDEX)) {
+ a = AddIndex.fromString(transactionId, arguments);
+ } else if (actionLabel.equals(Action.COMMIT)) {
+ a = Commit.fromString(transactionId, arguments);
+ } else if (actionLabel.equals(Action.CREATE_INDEX)) {
+ a = CreateIndex.fromString(transactionId, arguments);
+ } else if (actionLabel.equals(Action.DELETE_INDEX)) {
+ a = DeleteIndex.fromString(transactionId, arguments);
+ } else if (actionLabel.equals(Action.DELETE_NODE)) {
+ a = DeleteNode.fromString(transactionId, arguments);
+ } else if (actionLabel.equals(Action.START)) {
+ a = Start.fromString(transactionId, arguments);
+ } else if (actionLabel.equals(Action.VOLATILE_COMMIT)) {
+ a = VolatileCommit.fromString(transactionId, arguments);
+ } else {
+ throw new IllegalArgumentException(line);
+ }
+ return a;
+ }
+ }
- /**
- * Adds an index to the MultiIndex's active persistent index list.
- */
- private static class AddIndex extends Action
- {
+ /**
+ * Adds an index to the MultiIndex's active persistent index list.
+ */
+ private static class AddIndex extends Action {
- /**
- * The name of the index to add.
- */
- private String indexName;
+ /**
+ * The name of the index to add.
+ */
+ private String indexName;
- /**
- * Creates a new AddIndex action.
- *
- * @param transactionId the id of the transaction that executes this
- * action.
- * @param indexName the name of the index to add, or <code>null</code>
- * if an index with a new name should be created.
- */
- AddIndex(long transactionId, String indexName)
- {
- super(transactionId, Action.TYPE_ADD_INDEX);
- this.indexName = indexName;
- }
+ /**
+ * Creates a new AddIndex action.
+ *
+ * @param transactionId
+ * the id of the transaction that executes this action.
+ * @param indexName
+ * the name of the index to add, or <code>null</code> if an
+ * index with a new name should be created.
+ */
+ AddIndex(long transactionId, String indexName) {
+ super(transactionId, Action.TYPE_ADD_INDEX);
+ this.indexName = indexName;
+ }
- /**
- * Creates a new AddIndex action.
- *
- * @param transactionId the id of the transaction that executes this
- * action.
- * @param arguments the name of the index to add.
- * @return the AddIndex action.
- * @throws IllegalArgumentException if the arguments are malformed.
- */
- static AddIndex fromString(long transactionId, String arguments)
- {
- return new AddIndex(transactionId, arguments);
- }
+ /**
+ * Creates a new AddIndex action.
+ *
+ * @param transactionId
+ * the id of the transaction that executes this action.
+ * @param arguments
+ * the name of the index to add.
+ * @return the AddIndex action.
+ * @throws IllegalArgumentException
+ * if the arguments are malformed.
+ */
+ static AddIndex fromString(long transactionId, String arguments) {
+ return new AddIndex(transactionId, arguments);
+ }
- /**
- * Adds a sub index to <code>index</code>.
- *
- * @inheritDoc
- */
- public void execute(MultiIndex index) throws IOException
- {
- PersistentIndex idx = index.getOrCreateIndex(indexName);
- if (!index.indexNames.contains(indexName))
- {
- index.indexNames.addName(indexName);
- // now that the index is in the active list let the merger know about it
- index.merger.indexAdded(indexName, idx.getNumDocuments());
- }
- }
+ /**
+ * Adds a sub index to <code>index</code>.
+ *
+ * @inheritDoc
+ */
+ public void execute(MultiIndex index) throws IOException {
+ PersistentIndex idx = index.getOrCreateIndex(indexName);
+ if (!index.indexNames.contains(indexName)) {
+ index.indexNames.addName(indexName);
+ // now that the index is in the active list let the merger know
+ // about it
+ index.merger.indexAdded(indexName, idx.getNumDocuments());
+ }
+ }
- /**
- * @inheritDoc
- */
- public String toString()
- {
- StringBuffer logLine = new StringBuffer();
- logLine.append(Long.toString(getTransactionId()));
- logLine.append(' ');
- logLine.append(Action.ADD_INDEX);
- logLine.append(' ');
- logLine.append(indexName);
- return logLine.toString();
- }
- }
+ /**
+ * @inheritDoc
+ */
+ public String toString() {
+ StringBuffer logLine = new StringBuffer();
+ logLine.append(Long.toString(getTransactionId()));
+ logLine.append(' ');
+ logLine.append(Action.ADD_INDEX);
+ logLine.append(' ');
+ logLine.append(indexName);
+ return logLine.toString();
+ }
+ }
- /**
- * Adds a node to the index.
- */
- private static class AddNode extends Action
- {
+ /**
+ * Adds a node to the index.
+ */
+ private static class AddNode extends Action {
- /**
- * The maximum length of a AddNode String.
- */
- private static final int ENTRY_LENGTH =
- Long.toString(Long.MAX_VALUE).length() + Action.ADD_NODE.length() + Constants.UUID_FORMATTED_LENGTH + 2;
+ /**
+ * The maximum length of a AddNode String.
+ */
+ private static final int ENTRY_LENGTH = Long.toString(Long.MAX_VALUE)
+ .length()
+ + Action.ADD_NODE.length()
+ + Constants.UUID_FORMATTED_LENGTH
+ + 2;
- /**
- * The uuid of the node to add.
- */
- private final String uuid;
+ /**
+ * The uuid of the node to add.
+ */
+ private final String uuid;
- /**
- * The document to add to the index, or <code>null</code> if not available.
- */
- private Document doc;
+ /**
+ * The document to add to the index, or <code>null</code> if not
+ * available.
+ */
+ private Document doc;
- /**
- * Creates a new AddNode action.
- *
- * @param transactionId the id of the transaction that executes this action.
- * @param uuid the uuid of the node to add.
- */
- AddNode(long transactionId, String uuid)
- {
- super(transactionId, Action.TYPE_ADD_NODE);
- this.uuid = uuid;
- }
+ /**
+ * Creates a new AddNode action.
+ *
+ * @param transactionId
+ * the id of the transaction that executes this action.
+ * @param uuid
+ * the uuid of the node to add.
+ */
+ AddNode(long transactionId, String uuid) {
+ super(transactionId, Action.TYPE_ADD_NODE);
+ this.uuid = uuid;
+ }
- /**
- * Creates a new AddNode action.
- *
- * @param transactionId the id of the transaction that executes this action.
- * @param doc the document to add.
- */
- AddNode(long transactionId, Document doc)
- {
- this(transactionId, doc.get(FieldNames.UUID));
- this.doc = doc;
- }
+ /**
+ * Creates a new AddNode action.
+ *
+ * @param transactionId
+ * the id of the transaction that executes this action.
+ * @param doc
+ * the document to add.
+ */
+ AddNode(long transactionId, Document doc) {
+ this(transactionId, doc.get(FieldNames.UUID));
+ this.doc = doc;
+ }
- /**
- * Creates a new AddNode action.
- *
- * @param transactionId the id of the transaction that executes this
- * action.
- * @param arguments the arguments to this action. The uuid of the node
- * to add
- * @return the AddNode action.
- * @throws IllegalArgumentException if the arguments are malformed. Not a
- * UUID.
- */
- static AddNode fromString(long transactionId, String arguments) throws IllegalArgumentException
- {
- // simple length check
- if (arguments.length() != Constants.UUID_FORMATTED_LENGTH)
- {
- throw new IllegalArgumentException("arguments is not a uuid");
- }
- return new AddNode(transactionId, arguments);
- }
+ /**
+ * Creates a new AddNode action.
+ *
+ * @param transactionId
+ * the id of the transaction that executes this action.
+ * @param arguments
+ * the arguments to this action. The uuid of the node to add
+ * @return the AddNode action.
+ * @throws IllegalArgumentException
+ * if the arguments are malformed. Not a UUID.
+ */
+ static AddNode fromString(long transactionId, String arguments)
+ throws IllegalArgumentException {
+ // simple length check
+ if (arguments.length() != Constants.UUID_FORMATTED_LENGTH) {
+ throw new IllegalArgumentException("arguments is not a uuid");
+ }
+ return new AddNode(transactionId, arguments);
+ }
- /**
- * Adds a node to the index.
- *
- * @inheritDoc
- */
- public void execute(MultiIndex index) throws IOException
- {
- if (doc == null)
- {
- try
- {
- doc = index.createDocument(uuid);
- }
- catch (RepositoryException e)
- {
- // node does not exist anymore
- log.debug(e.getMessage());
- }
- }
- if (doc != null)
- {
- index.volatileIndex.addDocuments(new Document[]{doc});
- }
- }
+ /**
+ * Adds a node to the index.
+ *
+ * @inheritDoc
+ */
+ public void execute(MultiIndex index) throws IOException {
+ if (doc == null) {
+ try {
+ doc = index.createDocument(uuid);
+ } catch (RepositoryException e) {
+ // node does not exist anymore
+ log.debug(e.getMessage());
+ }
+ }
+ if (doc != null) {
+ index.volatileIndex.addDocuments(new Document[] { doc });
+ }
+ }
- /**
- * @inheritDoc
- */
- public String toString()
- {
- StringBuffer logLine = new StringBuffer(ENTRY_LENGTH);
- logLine.append(Long.toString(getTransactionId()));
- logLine.append(' ');
- logLine.append(Action.ADD_NODE);
- logLine.append(' ');
- logLine.append(uuid);
- return logLine.toString();
- }
- }
+ /**
+ * @inheritDoc
+ */
+ public String toString() {
+ StringBuffer logLine = new StringBuffer(ENTRY_LENGTH);
+ logLine.append(Long.toString(getTransactionId()));
+ logLine.append(' ');
+ logLine.append(Action.ADD_NODE);
+ logLine.append(' ');
+ logLine.append(uuid);
+ return logLine.toString();
+ }
+ }
- /**
- * Commits a transaction.
- */
- private static class Commit extends Action
- {
+ /**
+ * Commits a transaction.
+ */
+ private static class Commit extends Action {
- /**
- * Creates a new Commit action.
- *
- * @param transactionId the id of the transaction that is committed.
- */
- Commit(long transactionId)
- {
- super(transactionId, Action.TYPE_COMMIT);
- }
+ /**
+ * Creates a new Commit action.
+ *
+ * @param transactionId
+ * the id of the transaction that is committed.
+ */
+ Commit(long transactionId) {
+ super(transactionId, Action.TYPE_COMMIT);
+ }
- /**
- * Creates a new Commit action.
- *
- * @param transactionId the id of the transaction that executes this
- * action.
- * @param arguments ignored by this method.
- * @return the Commit action.
- */
- static Commit fromString(long transactionId, String arguments)
- {
- return new Commit(transactionId);
- }
+ /**
+ * Creates a new Commit action.
+ *
+ * @param transactionId
+ * the id of the transaction that executes this action.
+ * @param arguments
+ * ignored by this method.
+ * @return the Commit action.
+ */
+ static Commit fromString(long transactionId, String arguments) {
+ return new Commit(transactionId);
+ }
- /**
- * Touches the last flush time (sets it to the current time).
- *
- * @inheritDoc
- */
- public void execute(MultiIndex index) throws IOException
- {
- index.lastFlushTime = System.currentTimeMillis();
- }
+ /**
+ * Touches the last flush time (sets it to the current time).
+ *
+ * @inheritDoc
+ */
+ public void execute(MultiIndex index) throws IOException {
+ index.lastFlushTime = System.currentTimeMillis();
+ }
- /**
- * @inheritDoc
- */
- public String toString()
- {
- return Long.toString(getTransactionId()) + ' ' + Action.COMMIT;
- }
- }
+ /**
+ * @inheritDoc
+ */
+ public String toString() {
+ return Long.toString(getTransactionId()) + ' ' + Action.COMMIT;
+ }
+ }
- /**
- * Creates an new sub index but does not add it to the active persistent index
- * list.
- */
- private static class CreateIndex extends Action
- {
+ /**
+ * Creates an new sub index but does not add it to the active persistent
+ * index list.
+ */
+ private static class CreateIndex extends Action {
- /**
- * The name of the index to add.
- */
- private String indexName;
+ /**
+ * The name of the index to add.
+ */
+ private String indexName;
- /**
- * Creates a new CreateIndex action.
- *
- * @param transactionId the id of the transaction that executes this
- * action.
- * @param indexName the name of the index to add, or <code>null</code>
- * if an index with a new name should be created.
- */
- CreateIndex(long transactionId, String indexName)
- {
- super(transactionId, Action.TYPE_CREATE_INDEX);
- this.indexName = indexName;
- }
+ /**
+ * Creates a new CreateIndex action.
+ *
+ * @param transactionId
+ * the id of the transaction that executes this action.
+ * @param indexName
+ * the name of the index to add, or <code>null</code> if an
+ * index with a new name should be created.
+ */
+ CreateIndex(long transactionId, String indexName) {
+ super(transactionId, Action.TYPE_CREATE_INDEX);
+ this.indexName = indexName;
+ }
- /**
- * Creates a new CreateIndex action.
- *
- * @param transactionId the id of the transaction that executes this
- * action.
- * @param arguments the name of the index to create.
- * @return the AddIndex action.
- * @throws IllegalArgumentException if the arguments are malformed.
- */
- static CreateIndex fromString(long transactionId, String arguments)
- {
- // when created from String, this action is executed as redo action
- return new CreateIndex(transactionId, arguments);
- }
+ /**
+ * Creates a new CreateIndex action.
+ *
+ * @param transactionId
+ * the id of the transaction that executes this action.
+ * @param arguments
+ * the name of the index to create.
+ * @return the AddIndex action.
+ * @throws IllegalArgumentException
+ * if the arguments are malformed.
+ */
+ static CreateIndex fromString(long transactionId, String arguments) {
+ // when created from String, this action is executed as redo action
+ return new CreateIndex(transactionId, arguments);
+ }
- /**
- * Creates a new index.
- *
- * @inheritDoc
- */
- public void execute(MultiIndex index) throws IOException
- {
- PersistentIndex idx = index.getOrCreateIndex(indexName);
- indexName = idx.getName();
- }
+ /**
+ * Creates a new index.
+ *
+ * @inheritDoc
+ */
+ public void execute(MultiIndex index) throws IOException {
+ PersistentIndex idx = index.getOrCreateIndex(indexName);
+ indexName = idx.getName();
+ }
- /**
- * @inheritDoc
- */
- public void undo(MultiIndex index) throws IOException
- {
- if (index.hasIndex(indexName))
- {
- PersistentIndex idx = index.getOrCreateIndex(indexName);
- idx.close();
- index.deleteIndex(idx);
- }
- }
+ /**
+ * @inheritDoc
+ */
+ public void undo(MultiIndex index) throws IOException {
+ if (index.hasIndex(indexName)) {
+ PersistentIndex idx = index.getOrCreateIndex(indexName);
+ idx.close();
+ index.deleteIndex(idx);
+ }
+ }
- /**
- * @inheritDoc
- */
- public String toString()
- {
- StringBuffer logLine = new StringBuffer();
- logLine.append(Long.toString(getTransactionId()));
- logLine.append(' ');
- logLine.append(Action.CREATE_INDEX);
- logLine.append(' ');
- logLine.append(indexName);
- return logLine.toString();
- }
+ /**
+ * @inheritDoc
+ */
+ public String toString() {
+ StringBuffer logLine = new StringBuffer();
+ logLine.append(Long.toString(getTransactionId()));
+ logLine.append(' ');
+ logLine.append(Action.CREATE_INDEX);
+ logLine.append(' ');
+ logLine.append(indexName);
+ return logLine.toString();
+ }
- /**
- * Returns the index name that has been created. If this method is called
- * before {@link #execute(MultiIndex)} it will return <code>null</code>.
- *
- * @return the name of the index that has been created.
- */
- String getIndexName()
- {
- return indexName;
- }
- }
+ /**
+ * Returns the index name that has been created. If this method is
+ * called before {@link #execute(MultiIndex)} it will return
+ * <code>null</code>.
+ *
+ * @return the name of the index that has been created.
+ */
+ String getIndexName() {
+ return indexName;
+ }
+ }
- /**
- * Closes and deletes an index that is no longer in use.
- */
- private static class DeleteIndex extends Action
- {
+ /**
+ * Closes and deletes an index that is no longer in use.
+ */
+ private static class DeleteIndex extends Action {
- /**
- * The name of the index to add.
- */
- private String indexName;
+ /**
+ * The name of the index to add.
+ */
+ private String indexName;
- /**
- * Creates a new DeleteIndex action.
- *
- * @param transactionId the id of the transaction that executes this
- * action.
- * @param indexName the name of the index to delete.
- */
- DeleteIndex(long transactionId, String indexName)
- {
- super(transactionId, Action.TYPE_DELETE_INDEX);
- this.indexName = indexName;
- }
+ /**
+ * Creates a new DeleteIndex action.
+ *
+ * @param transactionId
+ * the id of the transaction that executes this action.
+ * @param indexName
+ * the name of the index to delete.
+ */
+ DeleteIndex(long transactionId, String indexName) {
+ super(transactionId, Action.TYPE_DELETE_INDEX);
+ this.indexName = indexName;
+ }
- /**
- * Creates a new DeleteIndex action.
- *
- * @param transactionId the id of the transaction that executes this
- * action.
- * @param arguments the name of the index to delete.
- * @return the DeleteIndex action.
- * @throws IllegalArgumentException if the arguments are malformed.
- */
- static DeleteIndex fromString(long transactionId, String arguments)
- {
- return new DeleteIndex(transactionId, arguments);
- }
+ /**
+ * Creates a new DeleteIndex action.
+ *
+ * @param transactionId
+ * the id of the transaction that executes this action.
+ * @param arguments
+ * the name of the index to delete.
+ * @return the DeleteIndex action.
+ * @throws IllegalArgumentException
+ * if the arguments are malformed.
+ */
+ static DeleteIndex fromString(long transactionId, String arguments) {
+ return new DeleteIndex(transactionId, arguments);
+ }
- /**
- * Removes a sub index from <code>index</code>.
- *
- * @inheritDoc
- */
- public void execute(MultiIndex index) throws IOException
- {
- // get index if it exists
- for (Iterator it = index.indexes.iterator(); it.hasNext();)
- {
- PersistentIndex idx = (PersistentIndex)it.next();
- if (idx.getName().equals(indexName))
- {
- idx.close();
- index.deleteIndex(idx);
- break;
- }
- }
- }
+ /**
+ * Removes a sub index from <code>index</code>.
+ *
+ * @inheritDoc
+ */
+ public void execute(MultiIndex index) throws IOException {
+ // get index if it exists
+ for (Iterator it = index.indexes.iterator(); it.hasNext();) {
+ PersistentIndex idx = (PersistentIndex) it.next();
+ if (idx.getName().equals(indexName)) {
+ idx.close();
+ index.deleteIndex(idx);
+ break;
+ }
+ }
+ }
- /**
- * @inheritDoc
- */
- public String toString()
- {
- StringBuffer logLine = new StringBuffer();
- logLine.append(Long.toString(getTransactionId()));
- logLine.append(' ');
- logLine.append(Action.DELETE_INDEX);
- logLine.append(' ');
- logLine.append(indexName);
- return logLine.toString();
- }
- }
+ /**
+ * @inheritDoc
+ */
+ public String toString() {
+ StringBuffer logLine = new StringBuffer();
+ logLine.append(Long.toString(getTransactionId()));
+ logLine.append(' ');
+ logLine.append(Action.DELETE_INDEX);
+ logLine.append(' ');
+ logLine.append(indexName);
+ return logLine.toString();
+ }
+ }
- /**
- * Deletes a node from the index.
- */
- private static class DeleteNode extends Action
- {
+ /**
+ * Deletes a node from the index.
+ */
+ private static class DeleteNode extends Action {
- /**
- * The maximum length of a DeleteNode String.
- */
- private static final int ENTRY_LENGTH =
- Long.toString(Long.MAX_VALUE).length() + Action.DELETE_NODE.length() + Constants.UUID_FORMATTED_LENGTH + 2;
+ /**
+ * The maximum length of a DeleteNode String.
+ */
+ private static final int ENTRY_LENGTH = Long.toString(Long.MAX_VALUE)
+ .length()
+ + Action.DELETE_NODE.length()
+ + Constants.UUID_FORMATTED_LENGTH
+ + 2;
- /**
- * The uuid of the node to remove.
- */
- private final String uuid;
+ /**
+ * The uuid of the node to remove.
+ */
+ private final String uuid;
- /**
- * Creates a new DeleteNode action.
- *
- * @param transactionId the id of the transaction that executes this action.
- * @param uuid the uuid of the node to delete.
- */
- DeleteNode(long transactionId, String uuid)
- {
- super(transactionId, Action.TYPE_DELETE_NODE);
- this.uuid = uuid;
- }
+ /**
+ * Creates a new DeleteNode action.
+ *
+ * @param transactionId
+ * the id of the transaction that executes this action.
+ * @param uuid
+ * the uuid of the node to delete.
+ */
+ DeleteNode(long transactionId, String uuid) {
+ super(transactionId, Action.TYPE_DELETE_NODE);
+ this.uuid = uuid;
+ }
- /**
- * Creates a new DeleteNode action.
- *
- * @param transactionId the id of the transaction that executes this
- * action.
- * @param arguments the uuid of the node to delete.
- * @return the DeleteNode action.
- * @throws IllegalArgumentException if the arguments are malformed. Not a
- * UUID.
- */
- static DeleteNode fromString(long transactionId, String arguments)
- {
- // simple length check
- if (arguments.length() != Constants.UUID_FORMATTED_LENGTH)
- {
- throw new IllegalArgumentException("arguments is not a uuid");
- }
- return new DeleteNode(transactionId, arguments);
- }
+ /**
+ * Creates a new DeleteNode action.
+ *
+ * @param transactionId
+ * the id of the transaction that executes this action.
+ * @param arguments
+ * the uuid of the node to delete.
+ * @return the DeleteNode action.
+ * @throws IllegalArgumentException
+ * if the arguments are malformed. Not a UUID.
+ */
+ static DeleteNode fromString(long transactionId, String arguments) {
+ // simple length check
+ if (arguments.length() != Constants.UUID_FORMATTED_LENGTH) {
+ throw new IllegalArgumentException("arguments is not a uuid");
+ }
+ return new DeleteNode(transactionId, arguments);
+ }
- /**
- * Deletes a node from the index.
- *
- * @inheritDoc
- */
- public void execute(MultiIndex index) throws IOException
- {
- String uuidString = uuid.toString();
- // check if indexing queue is still working on
- // this node from a previous update
- Document doc = index.indexingQueue.removeDocument(uuidString);
- if (doc != null)
- {
- Util.disposeDocument(doc);
- }
- Term idTerm = new Term(FieldNames.UUID, uuidString);
- // if the document cannot be deleted from the volatile index
- // delete it from one of the persistent indexes.
- int num = index.volatileIndex.removeDocument(idTerm);
- if (num == 0)
- {
- for (int i = index.indexes.size() - 1; i >= 0; i--)
- {
- // only look in registered indexes
- PersistentIndex idx = (PersistentIndex)index.indexes.get(i);
- if (index.indexNames.contains(idx.getName()))
- {
- num = idx.removeDocument(idTerm);
- if (num > 0)
- {
- return;
- }
- }
- }
- }
- }
+ /**
+ * Deletes a node from the index.
+ *
+ * @inheritDoc
+ */
+ public void execute(MultiIndex index) throws IOException {
+ String uuidString = uuid.toString();
+ // check if indexing queue is still working on
+ // this node from a previous update
+ Document doc = index.indexingQueue.removeDocument(uuidString);
+ if (doc != null) {
+ Util.disposeDocument(doc);
+ }
+ Term idTerm = new Term(FieldNames.UUID, uuidString);
+ // if the document cannot be deleted from the volatile index
+ // delete it from one of the persistent indexes.
+ int num = index.volatileIndex.removeDocument(idTerm);
+ if (num == 0) {
+ for (int i = index.indexes.size() - 1; i >= 0; i--) {
+ // only look in registered indexes
+ PersistentIndex idx = (PersistentIndex) index.indexes
+ .get(i);
+ if (index.indexNames.contains(idx.getName())) {
+ num = idx.removeDocument(idTerm);
+ if (num > 0) {
+ return;
+ }
+ }
+ }
+ }
+ }
- /**
- * @inheritDoc
- */
- public String toString()
- {
- StringBuffer logLine = new StringBuffer(ENTRY_LENGTH);
- logLine.append(Long.toString(getTransactionId()));
- logLine.append(' ');
- logLine.append(Action.DELETE_NODE);
- logLine.append(' ');
- logLine.append(uuid);
- return logLine.toString();
- }
- }
+ /**
+ * @inheritDoc
+ */
+ public String toString() {
+ StringBuffer logLine = new StringBuffer(ENTRY_LENGTH);
+ logLine.append(Long.toString(getTransactionId()));
+ logLine.append(' ');
+ logLine.append(Action.DELETE_NODE);
+ logLine.append(' ');
+ logLine.append(uuid);
+ return logLine.toString();
+ }
+ }
- /**
- * Starts a transaction.
- */
- private static class Start extends Action
- {
+ /**
+ * Starts a transaction.
+ */
+ private static class Start extends Action {
- /**
- * Creates a new Start transaction action.
- *
- * @param transactionId the id of the transaction that started.
- */
- Start(long transactionId)
- {
- super(transactionId, Action.TYPE_START);
- }
+ /**
+ * Creates a new Start transaction action.
+ *
+ * @param transactionId
+ * the id of the transaction that started.
+ */
+ Start(long transactionId) {
+ super(transactionId, Action.TYPE_START);
+ }
- /**
- * Creates a new Start action.
- *
- * @param transactionId the id of the transaction that executes this
- * action.
- * @param arguments ignored by this method.
- * @return the Start action.
- */
- static Start fromString(long transactionId, String arguments)
- {
- return new Start(transactionId);
- }
+ /**
+ * Creates a new Start action.
+ *
+ * @param transactionId
+ * the id of the transaction that executes this action.
+ * @param arguments
+ * ignored by this method.
+ * @return the Start action.
+ */
+ static Start fromString(long transactionId, String arguments) {
+ return new Start(transactionId);
+ }
- /**
- * Sets the current transaction id on <code>index</code>.
- *
- * @inheritDoc
- */
- public void execute(MultiIndex index) throws IOException
- {
- index.currentTransactionId = getTransactionId();
- }
+ /**
+ * Sets the current transaction id on <code>index</code>.
+ *
+ * @inheritDoc
+ */
+ public void execute(MultiIndex index) throws IOException {
+ index.currentTransactionId = getTransactionId();
+ }
- /**
- * @inheritDoc
- */
- public String toString()
- {
- return Long.toString(getTransactionId()) + ' ' + Action.START;
- }
- }
+ /**
+ * @inheritDoc
+ */
+ public String toString() {
+ return Long.toString(getTransactionId()) + ' ' + Action.START;
+ }
+ }
- /**
- * Commits the volatile index to disk.
- */
- private static class VolatileCommit extends Action
- {
+ /**
+ * Commits the volatile index to disk.
+ */
+ private static class VolatileCommit extends Action {
- /**
- * The name of the target index to commit to.
- */
- private final String targetIndex;
+ /**
+ * The name of the target index to commit to.
+ */
+ private final String targetIndex;
- /**
- * Creates a new VolatileCommit action.
- *
- * @param transactionId the id of the transaction that executes this action.
- */
- VolatileCommit(long transactionId, String targetIndex)
- {
- super(transactionId, Action.TYPE_VOLATILE_COMMIT);
- this.targetIndex = targetIndex;
- }
+ /**
+ * Creates a new VolatileCommit action.
+ *
+ * @param transactionId
+ * the id of the transaction that executes this action.
+ */
+ VolatileCommit(long transactionId, String targetIndex) {
+ super(transactionId, Action.TYPE_VOLATILE_COMMIT);
+ this.targetIndex = targetIndex;
+ }
- /**
- * Creates a new VolatileCommit action.
- *
- * @param transactionId the id of the transaction that executes this
- * action.
- * @param arguments ignored by this implementation.
- * @return the VolatileCommit action.
- */
- static VolatileCommit fromString(long transactionId, String arguments)
- {
- return new VolatileCommit(transactionId, arguments);
- }
+ /**
+ * Creates a new VolatileCommit action.
+ *
+ * @param transactionId
+ * the id of the transaction that executes this action.
+ * @param arguments
+ * ignored by this implementation.
+ * @return the VolatileCommit action.
+ */
+ static VolatileCommit fromString(long transactionId, String arguments) {
+ return new VolatileCommit(transactionId, arguments);
+ }
- /**
- * Commits the volatile index to disk.
- *
- * @inheritDoc
- */
- public void execute(MultiIndex index) throws IOException
- {
- VolatileIndex volatileIndex = index.getVolatileIndex();
- PersistentIndex persistentIndex = index.getOrCreateIndex(targetIndex);
- persistentIndex.copyIndex(volatileIndex);
- index.resetVolatileIndex();
- }
+ /**
+ * Commits the volatile index to disk.
+ *
+ * @inheritDoc
+ */
+ public void execute(MultiIndex index) throws IOException {
+ VolatileIndex volatileIndex = index.getVolatileIndex();
+ PersistentIndex persistentIndex = index
+ .getOrCreateIndex(targetIndex);
+ persistentIndex.copyIndex(volatileIndex);
+ index.resetVolatileIndex();
+ }
- /**
- * @inheritDoc
- */
- public String toString()
- {
- StringBuffer logLine = new StringBuffer();
- logLine.append(Long.toString(getTransactionId()));
- logLine.append(' ');
- logLine.append(Action.VOLATILE_COMMIT);
- logLine.append(' ');
- logLine.append(targetIndex);
- return logLine.toString();
- }
- }
+ /**
+ * @inheritDoc
+ */
+ public String toString() {
+ StringBuffer logLine = new StringBuffer();
+ logLine.append(Long.toString(getTransactionId()));
+ logLine.append(' ');
+ logLine.append(Action.VOLATILE_COMMIT);
+ logLine.append(' ');
+ logLine.append(targetIndex);
+ return logLine.toString();
+ }
+ }
}
Modified: jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SearchIndex.java
===================================================================
--- jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SearchIndex.java 2009-10-01 15:37:53 UTC (rev 193)
+++ jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SearchIndex.java 2009-10-02 08:25:49 UTC (rev 194)
@@ -38,7 +38,7 @@
import org.exoplatform.container.configuration.ConfigurationManager;
import org.exoplatform.services.document.DocumentReaderService;
import org.exoplatform.services.jcr.config.QueryHandlerEntry;
-import org.exoplatform.services.jcr.config.QueryHandlerEntryWrapper;
+import org.exoplatform.services.jcr.config.RepositoryConfigurationException;
import org.exoplatform.services.jcr.dataflow.ItemDataConsumer;
import org.exoplatform.services.jcr.datamodel.ItemData;
import org.exoplatform.services.jcr.datamodel.NodeData;
@@ -54,6 +54,7 @@
import org.exoplatform.services.jcr.impl.core.query.ExecutableQuery;
import org.exoplatform.services.jcr.impl.core.query.QueryHandler;
import org.exoplatform.services.jcr.impl.core.query.QueryHandlerContext;
+import org.exoplatform.services.jcr.impl.core.query.SearchIndexConfigurationHelper;
import org.exoplatform.services.jcr.impl.core.query.lucene.directory.DirectoryManager;
import org.exoplatform.services.jcr.impl.core.query.lucene.directory.FSDirectoryManager;
import org.slf4j.Logger;
@@ -379,7 +380,7 @@
*/
private SynonymProvider synProvider;
- private File indexDirectory;
+ // private File indexDirectory;
/**
* The configuration path for the synonym provider.
@@ -450,14 +451,14 @@
*/
private boolean closed = false;
- private QueryHandlerContext context;
+ // private QueryHandlerContext context;
/**
* Text extractor for extracting text content of binary properties.
*/
private DocumentReaderService extractor;
- private final QueryHandlerEntryWrapper queryHandlerConfig;
+ // private final QueryHandlerEntryWrapper queryHandlerConfig;
/**
* The ErrorLog of this <code>MultiIndex</code>. All changes that must be in
@@ -469,13 +470,20 @@
/**
* Working constructor.
+ *
+ * @throws RepositoryConfigurationException
+ * @throws IOException
*/
public SearchIndex(QueryHandlerEntry queryHandlerConfig,
- ConfigurationManager cfm) {
+ ConfigurationManager cfm) throws IOException,
+ RepositoryConfigurationException {
this.analyzer = new JcrStandartAnalyzer();
- this.queryHandlerConfig = new QueryHandlerEntryWrapper(
- queryHandlerConfig);
+ // this.queryHandlerConfig = new QueryHandlerEntryWrapper(
+ // queryHandlerConfig);
this.cfm = cfm;
+ SearchIndexConfigurationHelper searchIndexConfigurationHelper = new SearchIndexConfigurationHelper(
+ this);
+ searchIndexConfigurationHelper.init(queryHandlerConfig);
}
/**
@@ -483,23 +491,11 @@
*/
public SearchIndex() {
this.analyzer = new JcrStandartAnalyzer();
- this.queryHandlerConfig = null;
+ // this.queryHandlerConfig = null;
this.cfm = null;
}
/**
- * Initializes this query handler by setting all properties in this class
- * with appropriate parameter values.
- *
- * @param context
- * the context for this query handler.
- */
- public final void setContext(QueryHandlerContext queryHandlerContext)
- throws IOException {
- this.context = queryHandlerContext;
- }
-
- /**
* Initializes this <code>QueryHandler</code>. This implementation requires
* that a path parameter is set in the configuration. If this condition is
* not met, a <code>IOException</code> is thrown.
@@ -510,25 +506,25 @@
*/
public void doInit() throws IOException, RepositoryException {
QueryHandlerContext context = getContext();
- // if (path == null)
- // {
- // throw new
- // IOException("SearchIndex requires 'path' parameter in configuration!");
- // }
+ setPath(context.getIndexDirectory());
+ if (path == null) {
+ throw new IOException(
+ "SearchIndex requires 'path' parameter in configuration!");
+ }
- String indexDir = context.getIndexDirectory();
- if (indexDir != null) {
- indexDir = indexDir.replace("${java.io.tmpdir}", System
- .getProperty("java.io.tmpdir"));
- indexDirectory = new File(indexDir);
+ File indexDirectory;
+ if (path != null) {
+
+ indexDirectory = new File(path);
if (!indexDirectory.exists())
if (!indexDirectory.mkdirs())
throw new RepositoryException("fail to create index dir "
- + indexDir);
+ + path);
} else {
throw new IOException(
"SearchIndex requires 'path' parameter in configuration!");
}
+ log.info("path=" + path);
// Set excludedIDs = new HashSet();
// if (context.getExcludedNodeId() != null)
@@ -537,7 +533,7 @@
// }
extractor = context.getExtractor();
- synProvider = queryHandlerConfig.createSynonymProvider(cfm);
+ // synProvider = queryHandlerConfig.createSynonymProvider(cfm);
directoryManager = createDirectoryManager();
if (context.getParentHandler() instanceof SearchIndex) {
@@ -566,22 +562,10 @@
indexingConfig = createIndexingConfiguration(nsMappings);
analyzer.setIndexingConfig(indexingConfig);
- index = new MultiIndex(this, new HashSet<String>());
- if (index.numDocs() == 0) {
- // Path rootPath;
- // if (excludedIDs.isEmpty())
- // {
- // // this is the index for jcr:system
- // rootPath = JCR_SYSTEM_PATH;
- // }
- // else
- // {
- // rootPath = ROOT_PATH;
- // }
- // index.createInitialIndex(context.getItemStateManager(),
- // context.getRootId(), rootPath);
- index.createInitialIndex(context.getItemStateManager(), context
- .getRootNodeIdentifer());
+ index = new MultiIndex(this, context.getIndexingTree());
+ if (index.numDocs() == 0 && context.isCreateInitialIndex()) {
+
+ index.createInitialIndex(context.getItemStateManager());
}
if (consistencyCheckEnabled
&& (index.getRedoLogApplied() || forceConsistencyCheck)) {
@@ -1797,9 +1781,13 @@
*
* @param path
* the location of the search index.
+ * @throws IOException
*/
public void setPath(String path) {
- indexDirectory = new File(path);
+
+ this.path = path.replace("${java.io.tmpdir}", System
+ .getProperty("java.io.tmpdir"));
+
}
/**
@@ -1809,7 +1797,7 @@
* @return the location of the search index.
*/
public String getPath() {
- return indexDirectory.getAbsolutePath();
+ return path;
}
/**
Modified: jcr/trunk/component/core/src/test/java/org/exoplatform/services/jcr/api/core/query/TestAll.java
===================================================================
--- jcr/trunk/component/core/src/test/java/org/exoplatform/services/jcr/api/core/query/TestAll.java 2009-10-01 15:37:53 UTC (rev 193)
+++ jcr/trunk/component/core/src/test/java/org/exoplatform/services/jcr/api/core/query/TestAll.java 2009-10-02 08:25:49 UTC (rev 194)
@@ -25,43 +25,41 @@
/**
* Test suite that includes all testcases for the Search module.
*/
-public class TestAll extends TestCase
-{
+public class TestAll extends TestCase {
- /**
- * Returns a <code>Test</code> suite that executes all tests inside this
- * package.
- *
- * @return a <code>Test</code> suite that executes all tests inside this
- * package.
- */
- public static Test suite()
- {
- TestSuite suite = new TestSuite("Search tests");
+ /**
+ * Returns a <code>Test</code> suite that executes all tests inside this
+ * package.
+ *
+ * @return a <code>Test</code> suite that executes all tests inside this
+ * package.
+ */
+ public static Test suite() {
+ TestSuite suite = new TestSuite("Search tests");
- suite.addTestSuite(SimpleQueryTest.class);
- suite.addTestSuite(FulltextQueryTest.class);
- suite.addTestSuite(SelectClauseTest.class);
- suite.addTestSuite(SQLTest.class);
- suite.addTestSuite(OrderByTest.class);
- suite.addTestSuite(XPathAxisTest.class);
- suite.addTestSuite(SkipDeletedNodesTest.class);
- suite.addTestSuite(SkipDeniedNodesTest.class);
- suite.addTestSuite(MixinTest.class);
- suite.addTestSuite(DerefTest.class);
- suite.addTestSuite(VersionStoreQueryTest.class);
- suite.addTestSuite(UpperLowerCaseQueryTest.class);
- suite.addTestSuite(ChildAxisQueryTest.class);
- suite.addTestSuite(QueryResultTest.class);
- suite.addTestSuite(FnNameQueryTest.class);
- suite.addTestSuite(PathQueryNodeTest.class);
- suite.addTestSuite(SynonymProviderTest.class);
- suite.addTestSuite(ArrayHitsTest.class);
- //suite.addTestSuite(ExcerptTest.class);
- suite.addTestSuite(IndexFormatVersionTest.class);
- //suite.addTestSuite(IndexingRuleTest.class);
- suite.addTestSuite(ShareableNodeTest.class);
+ suite.addTestSuite(SimpleQueryTest.class);
+ suite.addTestSuite(FulltextQueryTest.class);
+ suite.addTestSuite(SelectClauseTest.class);
+ suite.addTestSuite(SQLTest.class);
+ suite.addTestSuite(OrderByTest.class);
+ suite.addTestSuite(XPathAxisTest.class);
+ suite.addTestSuite(SkipDeletedNodesTest.class);
+ suite.addTestSuite(SkipDeniedNodesTest.class);
+ suite.addTestSuite(MixinTest.class);
+ suite.addTestSuite(DerefTest.class);
+ suite.addTestSuite(VersionStoreQueryTest.class);
+ suite.addTestSuite(UpperLowerCaseQueryTest.class);
+ suite.addTestSuite(ChildAxisQueryTest.class);
+ suite.addTestSuite(QueryResultTest.class);
+ suite.addTestSuite(FnNameQueryTest.class);
+ suite.addTestSuite(PathQueryNodeTest.class);
+ // suite.addTestSuite(SynonymProviderTest.class);
+ suite.addTestSuite(ArrayHitsTest.class);
+ // suite.addTestSuite(ExcerptTest.class);
+ suite.addTestSuite(IndexFormatVersionTest.class);
+ // suite.addTestSuite(IndexingRuleTest.class);
+ suite.addTestSuite(ShareableNodeTest.class);
- return suite;
- }
+ return suite;
+ }
}
Modified: jcr/trunk/component/core/src/test/java/org/exoplatform/services/jcr/api/core/query/lucene/directory/DirectoryManagerTest.java
===================================================================
--- jcr/trunk/component/core/src/test/java/org/exoplatform/services/jcr/api/core/query/lucene/directory/DirectoryManagerTest.java 2009-10-01 15:37:53 UTC (rev 193)
+++ jcr/trunk/component/core/src/test/java/org/exoplatform/services/jcr/api/core/query/lucene/directory/DirectoryManagerTest.java 2009-10-02 08:25:49 UTC (rev 194)
@@ -16,19 +16,18 @@
*/
package org.exoplatform.services.jcr.api.core.query.lucene.directory;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Iterator;
-import java.io.File;
+import junit.framework.TestCase;
-
import org.apache.lucene.store.Directory;
import org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex;
import org.exoplatform.services.jcr.impl.core.query.lucene.directory.DirectoryManager;
import org.exoplatform.services.jcr.impl.core.query.lucene.directory.FSDirectoryManager;
import org.exoplatform.services.jcr.impl.core.query.lucene.directory.RAMDirectoryManager;
-import junit.framework.TestCase;
+import java.io.File;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
/**
* <code>DirectoryManagerTest</code> performs tests on directory manager
@@ -36,8 +35,9 @@
*/
public class DirectoryManagerTest extends TestCase {
- private static final Collection IMPLEMENTATIONS = Arrays.asList(
- new Class[]{FSDirectoryManager.class, RAMDirectoryManager.class});
+ private static final Collection IMPLEMENTATIONS = Arrays
+ .asList(new Class[] { FSDirectoryManager.class,
+ RAMDirectoryManager.class });
private static final SearchIndex INDEX = new SearchIndex();
@@ -46,69 +46,75 @@
private static final String RENAMED = "renamed";
static {
- INDEX.setPath(new File(new File("target"), "directory-factory-test").getAbsolutePath());
+ INDEX.setPath(new File(new File("target"), "directory-factory-test")
+ .getAbsolutePath());
}
protected void tearDown() throws Exception {
- new File(INDEX.getPath(), TEST).delete();
- new File(INDEX.getPath(), RENAMED).delete();
+ new File(INDEX.getPath(), TEST).delete();
+ new File(INDEX.getPath(), RENAMED).delete();
}
public void testHasDirectory() throws Exception {
- execute(new Callable(){
- public void call(DirectoryManager directoryManager) throws Exception {
- Directory dir = directoryManager.getDirectory(TEST);
- assertTrue(directoryManager.hasDirectory(TEST));
- dir.close();
- }
- });
+ execute(new Callable() {
+ public void call(DirectoryManager directoryManager)
+ throws Exception {
+ Directory dir = directoryManager.getDirectory(TEST);
+ assertTrue(directoryManager.hasDirectory(TEST));
+ dir.close();
+ }
+ });
}
public void testDelete() throws Exception {
- execute(new Callable(){
- public void call(DirectoryManager directoryManager) throws Exception {
- directoryManager.getDirectory(TEST).close();
- directoryManager.delete(TEST);
- assertFalse(directoryManager.hasDirectory(TEST));
- }
- });
+ execute(new Callable() {
+ public void call(DirectoryManager directoryManager)
+ throws Exception {
+ directoryManager.getDirectory(TEST).close();
+ directoryManager.delete(TEST);
+ assertFalse(directoryManager.hasDirectory(TEST));
+ }
+ });
}
public void testGetDirectoryNames() throws Exception {
- execute(new Callable(){
- public void call(DirectoryManager directoryManager) throws Exception {
- directoryManager.getDirectory(TEST).close();
- assertTrue(Arrays.asList(directoryManager.getDirectoryNames()).contains(TEST));
- }
- });
+ execute(new Callable() {
+ public void call(DirectoryManager directoryManager)
+ throws Exception {
+ directoryManager.getDirectory(TEST).close();
+ assertTrue(Arrays.asList(directoryManager.getDirectoryNames())
+ .contains(TEST));
+ }
+ });
}
public void testRename() throws Exception {
- execute(new Callable(){
- public void call(DirectoryManager directoryManager) throws Exception {
- directoryManager.getDirectory(TEST).close();
- directoryManager.rename(TEST, RENAMED);
- assertTrue(directoryManager.hasDirectory(RENAMED));
- assertFalse(directoryManager.hasDirectory(TEST));
- }
- });
+ execute(new Callable() {
+ public void call(DirectoryManager directoryManager)
+ throws Exception {
+ directoryManager.getDirectory(TEST).close();
+ directoryManager.rename(TEST, RENAMED);
+ assertTrue(directoryManager.hasDirectory(RENAMED));
+ assertFalse(directoryManager.hasDirectory(TEST));
+ }
+ });
}
private void execute(Callable callable) throws Exception {
- for (Iterator it = IMPLEMENTATIONS.iterator(); it.hasNext(); ) {
- Class clazz = (Class) it.next();
- DirectoryManager dirMgr = (DirectoryManager) clazz.newInstance();
- dirMgr.init(INDEX);
- try {
- callable.call(dirMgr);
- } finally {
- dirMgr.dispose();
- }
- }
+ for (Iterator it = IMPLEMENTATIONS.iterator(); it.hasNext();) {
+ Class clazz = (Class) it.next();
+ DirectoryManager dirMgr = (DirectoryManager) clazz.newInstance();
+ dirMgr.init(INDEX);
+ try {
+ callable.call(dirMgr);
+ } finally {
+ dirMgr.dispose();
+ }
+ }
}
private interface Callable {
- public void call(DirectoryManager directoryManager) throws Exception;
+ public void call(DirectoryManager directoryManager) throws Exception;
}
}
14 years, 7 months
exo-jcr SVN: r193 - jcr/trunk/component/core.
by do-not-reply@jboss.org
Author: pnedonosko
Date: 2009-10-01 11:37:53 -0400 (Thu, 01 Oct 2009)
New Revision: 193
Modified:
jcr/trunk/component/core/pom.xml
Log:
EXOJCR-161: new TCK adoption (2)
Modified: jcr/trunk/component/core/pom.xml
===================================================================
--- jcr/trunk/component/core/pom.xml 2009-10-01 15:36:02 UTC (rev 192)
+++ jcr/trunk/component/core/pom.xml 2009-10-01 15:37:53 UTC (rev 193)
@@ -518,6 +518,7 @@
<name>emma.coverage.out.file</name>
<value>target/emma/coverage.ec</value>
</property>
+ <property>
<name>known.issues</name>
<value>
org.apache.jackrabbit.test.api.nodetype.PropertyDefTest#testIsRequiredType
@@ -554,7 +555,7 @@
org.apache.jackrabbit.test.api.NamespaceRegistryTest#testRegisterNamespace
org.apache.jackrabbit.test.api.nodetype.PredefinedNodeTypeTest#testVersion
</value>
-
+ </property>
<!-- property>
<name>known.issues</name>
<value>
14 years, 7 months
exo-jcr SVN: r192 - in jcr/trunk: component/core and 1 other directory.
by do-not-reply@jboss.org
Author: pnedonosko
Date: 2009-10-01 11:36:02 -0400 (Thu, 01 Oct 2009)
New Revision: 192
Modified:
jcr/trunk/component/core/pom.xml
jcr/trunk/pom.xml
Log:
EXOJCR-161: new TCK adoption; deps on JR integration tests in the reactor
Modified: jcr/trunk/component/core/pom.xml
===================================================================
--- jcr/trunk/component/core/pom.xml 2009-10-01 09:18:31 UTC (rev 191)
+++ jcr/trunk/component/core/pom.xml 2009-10-01 15:36:02 UTC (rev 192)
@@ -175,7 +175,6 @@
<dependency>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>jackrabbit-jcr-tests</artifactId>
- <version>1.6.0</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
@@ -364,25 +363,55 @@
<!-- debug mode: mvn -Dmaven.test.skip=false -Dexo.tck.skip=false -DforkMode=never clean install -->
<!-- forking: to run both eXo test and TCK use forkMode=once, to run one of them (only) in Eclipse debug use forkMode=never -->
<configuration>
- <argLine>-Xmx512M</argLine>
- <systemProperties>
- <property>
- <name>jcr.test.configuration.file</name>
- <value>${jcr.test.configuration.file}</value>
- </property>
- <property>
- <name>emma.coverage.out.file</name>
- <value>target/emma/coverage.ec</value>
- </property>
- </systemProperties>
- <includes>
- <!-- include>**/api/core/query/TestAll.java</include-->
-
+ <skip>true</skip>
+ </configuration>
+ <executions>
+ <execution>
+ <id>execution0 - developers tests</id>
+ <phase>test</phase>
+ <goals>
+ <goal>test</goal>
+ </goals>
+ <configuration>
+ <skip>${exo.devtest.skip}</skip>
+ <systemProperties>
+ <property>
+ <name>jcr.test.configuration.file</name>
+ <value>${jcr.test.configuration.file}</value>
+ </property>
+ </systemProperties>
+ <includes>
+ <include>**/**/TestErrorMultithreading__.java</include>
+ <include>**/**/TestConcurrentItems__.java</include>
+ <include>**/**/TestInvalidItemState__.java</include>
+ </includes>
+ </configuration>
+ </execution>
+ <execution>
+ <id>execution1 - exo tests</id>
+ <phase>test</phase>
+ <goals>
+ <goal>test</goal>
+ </goals>
+ <configuration>
+ <skip>${exo.test.skip}</skip>
+ <argLine>-Xmx512M</argLine>
+ <systemProperties>
+ <property>
+ <name>jcr.test.configuration.file</name>
+ <value>${jcr.test.configuration.file}</value>
+ </property>
+ <property>
+ <name>emma.coverage.out.file</name>
+ <value>target/emma/coverage.ec</value>
+ </property>
+ </systemProperties>
+ <includes>
<include>**/api/**/Test*.java</include>
<include>**/usecases/**/Test*.java</include>
<include>**/usecases/**/*Test.java</include>
<include>**/impl/**/Test*.java</include>
- </includes>
+ </includes>
<excludes>
<exclude>**/ExcerptTest.java</exclude>
<exclude>**/TestSearchManagerIndexing.java</exclude>
@@ -423,23 +452,72 @@
<exclude>**/api/**/TestSameNameItems.java</exclude>
<exclude>**/api/**/TestVersionRestore.java</exclude>
</excludes>
- </configuration>
- <executions>
+ </configuration>
+ </execution>
+ <!-- execution>
+ <id>execution2 - pause 10 sec</id>
+ <phase>test</phase>
+ <goals>
+ <goal>test</goal>
+ </goals>
+ <configuration>
+ <skip>${exo.tck.skip}</skip>
+ <includes>
+ <include>**/util/Sleeping10Seconds.java</include>
+ </includes>
+ </configuration>
+ </execution>
<execution>
- <id>do_test</id>
- <phase>integration-test</phase>
+ <id>execution3 - TCK init section</id>
+ <phase>test</phase>
+ <goals>
+ <goal>test</goal>
+ </goals>
<configuration>
+ <skip>${exo.tck.skip}</skip>
<argLine>-Xmx512M</argLine>
<systemProperties>
<property>
<name>jcr.test.configuration.file</name>
<value>${jcr.test.configuration.file}</value>
</property>
+ </systemProperties>
+ <includes>
+ <include>org/exoplatform/services/jcr/integration/PrepareTestRepository.java</include>
+ </includes>
+ </configuration>
+ </execution -->
+ <execution>
+ <id>execution4 - pause 10 sec</id>
+ <phase>test</phase>
+ <goals>
+ <goal>test</goal>
+ </goals>
+ <configuration>
+ <skip>${exo.tck.skip}</skip>
+ <includes>
+ <include>**/util/Sleeping10Seconds.java</include>
+ </includes>
+ </configuration>
+ </execution>
+ <execution>
+ <id>execution5 - integration tests (TCK)</id>
+ <phase>test</phase>
+ <goals>
+ <goal>test</goal>
+ </goals>
+ <configuration>
+ <skip>${exo.tck.skip}</skip>
+ <argLine>-Xmx512M</argLine>
+ <systemProperties>
<property>
+ <name>jcr.test.configuration.file</name>
+ <value>${jcr.test.configuration.file}</value>
+ </property>
+ <property>
<name>emma.coverage.out.file</name>
<value>target/emma/coverage.ec</value>
</property>
- <property>
<name>known.issues</name>
<value>
org.apache.jackrabbit.test.api.nodetype.PropertyDefTest#testIsRequiredType
@@ -452,7 +530,7 @@
org.apache.jackrabbit.test.api.SetValueConstraintViolationExceptionTest#testBooleanProperty
org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreName
org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreOrder
- org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreOrder2
+ org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreOrder2
org.apache.jackrabbit.test.api.NamespaceRegistryTest#testRegisterNamespace
org.apache.jackrabbit.test.api.SetValueConstraintViolationExceptionTest#testBooleanProperty
org.apache.jackrabbit.test.api.SetValueConstraintViolationExceptionTest#testMultipleBooleanProperty
@@ -464,27 +542,51 @@
org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreOrder
org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreOrder2
org.apache.jackrabbit.test.api.NamespaceRegistryTest#testRegisterNamespace
- org.apache.jackrabbit.test.api.SetValueConstraintViolationExceptionTest#testBooleanProperty
- org.apache.jackrabbit.test.api.SetValueConstraintViolationExceptionTest#testMultipleBooleanProperty
- org.apache.jackrabbit.test.api.SetPropertyConstraintViolationExceptionTest#testBooleanProperty
- org.apache.jackrabbit.test.api.nodetype.PropertyDefTest#testIsRequiredType
- org.apache.jackrabbit.test.api.nodetype.PredefinedNodeTypeTest#testVersionable
- org.apache.jackrabbit.test.api.version.RestoreTest#testVersion
- org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreName
- org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreOrder
- org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreOrder2
+ org.apache.jackrabbit.test.api.SetValueConstraintViolationExceptionTest#testBooleanProperty
+ org.apache.jackrabbit.test.api.SetValueConstraintViolationExceptionTest#testMultipleBooleanProperty
+ org.apache.jackrabbit.test.api.SetPropertyConstraintViolationExceptionTest#testBooleanProperty
+ org.apache.jackrabbit.test.api.nodetype.PropertyDefTest#testIsRequiredType
+ org.apache.jackrabbit.test.api.nodetype.PredefinedNodeTypeTest#testVersionable
+ org.apache.jackrabbit.test.api.version.RestoreTest#testVersion
+ org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreName
+ org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreOrder
+ org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreOrder2
org.apache.jackrabbit.test.api.NamespaceRegistryTest#testRegisterNamespace
- org.apache.jackrabbit.test.api.nodetype.PredefinedNodeTypeTest#testVersion
- </value>
- </property>
+ org.apache.jackrabbit.test.api.nodetype.PredefinedNodeTypeTest#testVersion
+ </value>
+
+ <!-- property>
+ <name>known.issues</name>
+ <value>
+ org.apache.jackrabbit.test.api.nodetype.PropertyDefTest#testIsRequiredType
+ org.apache.jackrabbit.test.api.DocumentViewImportTest#testSessionImportXml
+ org.apache.jackrabbit.test.api.DocumentViewImportTest#testWorkspaceImportXml
+ org.apache.jackrabbit.test.api.DocumentViewImportTest#testWorkspaceGetImportContentHandler
+ org.apache.jackrabbit.test.api.DocumentViewImportTest#testSessionGetImportContentHandler
+ org.apache.jackrabbit.test.api.SetPropertyConstraintViolationExceptionTest#testBooleanProperty
+ org.apache.jackrabbit.test.api.SetValueConstraintViolationExceptionTest#testMultipleBooleanProperty
+ org.apache.jackrabbit.test.api.SetValueConstraintViolationExceptionTest#testBooleanProperty
+ org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreName
+ org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreOrder
+ org.apache.jackrabbit.test.api.version.RestoreTest#testRestoreOrder2
+ </value>
+ </property -->
</systemProperties>
<includes>
- <include>**/integration/*Test.java</include>
+ <include>**/api/*Test.java</include>
+ <include>**/api/observation/*Test.java</include>
+ <include>**/api/lock/*Test.java</include>
+ <include>**/api/nodetype/*Test.java</include>
+ <include>**/api/query/*Test.java</include>
+ <include>**/api/version/*Test.java</include>
</includes>
+ <excludes>
+ <exclude>**/api/TestAll.java</exclude>
+ <exclude>**/api/**/Abstract*.java</exclude>
+ <exclude>**/api/**/FrozenNodeTest.java</exclude>
+ <exclude>**/exoplatform/**</exclude>
+ </excludes>
</configuration>
- <goals>
- <goal>test</goal>
- </goals>
</execution>
</executions>
</plugin>
@@ -517,7 +619,7 @@
<tasks>
<echo>Remove files that have been customized</echo>
<delete>
- <fileset dir="${project.build.directory}/generated-sources/javacc/org/exoplatform/services/jcr/impl/core/query">
+ <fileset dir="${project.build.directory}/generated-sources/javacc/org/exoplatform/services/jcr/impl/core/query">
<include name="sql/ASTLiteral.java" />
<include name="sql/ASTContainsExpression.java" />
<include name="sql/ASTPredicate.java" />
Modified: jcr/trunk/pom.xml
===================================================================
--- jcr/trunk/pom.xml 2009-10-01 09:18:31 UTC (rev 191)
+++ jcr/trunk/pom.xml 2009-10-01 15:36:02 UTC (rev 192)
@@ -237,7 +237,7 @@
<dependency>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>jackrabbit-jcr-tests</artifactId>
- <version>1.4</version>
+ <version>1.6.0</version>
</dependency>
<!-- slf4j-log4j12 for TCK sources -->
14 years, 7 months
exo-jcr SVN: r191 - jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene.
by do-not-reply@jboss.org
Author: skabashnyuk
Date: 2009-10-01 05:18:31 -0400 (Thu, 01 Oct 2009)
New Revision: 191
Modified:
jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/RowIteratorImpl.java
jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SpellSuggestion.java
Log:
EXOJCR-161 : Exception handling
Modified: jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/RowIteratorImpl.java
===================================================================
--- jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/RowIteratorImpl.java 2009-10-01 09:14:03 UTC (rev 190)
+++ jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/RowIteratorImpl.java 2009-10-01 09:18:31 UTC (rev 191)
@@ -16,6 +16,18 @@
*/
package org.exoplatform.services.jcr.impl.core.query.lucene;
+import org.exoplatform.services.jcr.datamodel.InternalQName;
+import org.exoplatform.services.jcr.datamodel.ItemData;
+import org.exoplatform.services.jcr.impl.Constants;
+import org.exoplatform.services.jcr.impl.core.LocationFactory;
+import org.exoplatform.services.jcr.impl.core.NodeImpl;
+import org.exoplatform.services.jcr.impl.core.PropertyImpl;
+import org.exoplatform.services.jcr.impl.core.SessionDataManager;
+import org.exoplatform.services.jcr.impl.core.value.ValueFactoryImpl;
+import org.exoplatform.services.jcr.impl.util.ISO9075;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
@@ -36,39 +48,27 @@
import javax.jcr.query.Row;
import javax.jcr.query.RowIterator;
-import org.exoplatform.services.jcr.datamodel.InternalQName;
-import org.exoplatform.services.jcr.datamodel.ItemData;
-import org.exoplatform.services.jcr.impl.Constants;
-import org.exoplatform.services.jcr.impl.core.ItemImpl;
-import org.exoplatform.services.jcr.impl.core.LocationFactory;
-import org.exoplatform.services.jcr.impl.core.NodeImpl;
-import org.exoplatform.services.jcr.impl.core.PropertyImpl;
-import org.exoplatform.services.jcr.impl.core.SessionDataManager;
-
-
-import org.exoplatform.services.jcr.impl.core.value.ValueFactoryImpl;
-import org.exoplatform.services.jcr.impl.util.ISO9075;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
/**
- * Implements the {@link javax.jcr.query.RowIterator} interface returned by
- * a {@link javax.jcr.query.QueryResult}.
+ * Implements the {@link javax.jcr.query.RowIterator} interface returned by a
+ * {@link javax.jcr.query.QueryResult}.
*/
class RowIteratorImpl implements RowIterator {
/**
* The logger instance for this class.
*/
- private static final Logger log = LoggerFactory.getLogger(RowIteratorImpl.class);
+ private static final Logger log = LoggerFactory
+ .getLogger(RowIteratorImpl.class);
/**
* The QValue factory.
*/
- //private static final QValueFactory QVALUE_FACTORY = QValueFactoryImpl.getInstance();
+ // private static final QValueFactory QVALUE_FACTORY =
+ // QValueFactoryImpl.getInstance();
/**
- * The name of the excerpt function without prefix but with left parenthesis.
+ * The name of the excerpt function without prefix but with left
+ * parenthesis.
*/
private static final String EXCERPT_FUNC_LPAR = "excerpt(";
@@ -81,7 +81,8 @@
/**
* The start Name for the rep:excerpt function: rep:excerpt(
*/
- private static final InternalQName REP_EXCERPT_LPAR = new InternalQName(Constants.NS_REP_URI, EXCERPT_FUNC_LPAR);
+ private static final InternalQName REP_EXCERPT_LPAR = new InternalQName(
+ Constants.NS_REP_URI, EXCERPT_FUNC_LPAR);
/**
* Iterator over nodes, that constitute the result set.
@@ -108,7 +109,6 @@
*/
private final SessionDataManager itemMgr;
-
/**
* The <code>NamePathResolver</code> of the user <code>Session</code>.
*/
@@ -132,623 +132,652 @@
/**
* Creates a new <code>RowIteratorImpl</code> that iterates over the result
* nodes.
- *
- * @param scoreNodes a <code>ScoreNodeIterator</code> that contains the
- * nodes of the query result.
- * @param properties <code>Name</code> of the select properties.
- * @param selectorNames the selector names.
- * @param itemMgr the item manager of the session that executes the
- * query.
- * @param hmgr the hierarchy manager of the workspace.
- * @param resolver <code>NamespaceResolver</code> of the user
- * <code>Session</code>.
- * @param exProvider the excerpt provider associated with the query
- * result that created this row iterator.
- * @param spellSuggestion the spell suggestion associated with the query
- * result or <code>null</code> if none is available.
+ *
+ * @param scoreNodes
+ * a <code>ScoreNodeIterator</code> that contains the nodes of
+ * the query result.
+ * @param properties
+ * <code>Name</code> of the select properties.
+ * @param selectorNames
+ * the selector names.
+ * @param itemMgr
+ * the item manager of the session that executes the query.
+ * @param hmgr
+ * the hierarchy manager of the workspace.
+ * @param resolver
+ * <code>NamespaceResolver</code> of the user
+ * <code>Session</code>.
+ * @param exProvider
+ * the excerpt provider associated with the query result that
+ * created this row iterator.
+ * @param spellSuggestion
+ * the spell suggestion associated with the query result or
+ * <code>null</code> if none is available.
*/
-
- RowIteratorImpl(ScoreNodeIterator scoreNodes,
- InternalQName[] properties,
- InternalQName[] selectorNames,
- SessionDataManager itemMgr,
-
- LocationFactory resolver,
- ExcerptProvider exProvider,
- SpellSuggestion spellSuggestion) {
- this.scoreNodes = scoreNodes;
- this.properties = properties;
- this.selectorNames.addAll(Arrays.asList(selectorNames));
- this.itemMgr = itemMgr;
- this.resolver = resolver;
- this.excerptProvider = exProvider;
- this.spellSuggestion = spellSuggestion;
- this.valueFactory = new ValueFactoryImpl( resolver);
+
+ RowIteratorImpl(ScoreNodeIterator scoreNodes, InternalQName[] properties,
+ InternalQName[] selectorNames, SessionDataManager itemMgr,
+
+ LocationFactory resolver, ExcerptProvider exProvider,
+ SpellSuggestion spellSuggestion) {
+ this.scoreNodes = scoreNodes;
+ this.properties = properties;
+ this.selectorNames.addAll(Arrays.asList(selectorNames));
+ this.itemMgr = itemMgr;
+ this.resolver = resolver;
+ this.excerptProvider = exProvider;
+ this.spellSuggestion = spellSuggestion;
+ this.valueFactory = new ValueFactoryImpl(resolver);
}
/**
* Returns the next <code>Row</code> in the iteration.
- *
+ *
* @return the next <code>Row</code> in the iteration.
- * @throws NoSuchElementException if iteration has no more
- * <code>Row</code>s.
+ * @throws NoSuchElementException
+ * if iteration has no more <code>Row</code>s.
*/
public Row nextRow() throws NoSuchElementException {
- return new RowImpl(scoreNodes.nextScoreNodes());
+ return new RowImpl(scoreNodes.nextScoreNodes());
}
/**
* Skip a number of <code>Row</code>s in this iterator.
- *
- * @param skipNum the non-negative number of <code>Row</code>s to skip
- * @throws NoSuchElementException if skipped past the last
- * <code>Row</code> in this iterator.
+ *
+ * @param skipNum
+ * the non-negative number of <code>Row</code>s to skip
+ * @throws NoSuchElementException
+ * if skipped past the last <code>Row</code> in this iterator.
*/
public void skip(long skipNum) throws NoSuchElementException {
- scoreNodes.skip(skipNum);
+ scoreNodes.skip(skipNum);
}
/**
* Returns the number of <code>Row</code>s in this iterator.
- *
+ *
* @return the number of <code>Row</code>s in this iterator.
*/
public long getSize() {
- return scoreNodes.getSize();
+ return scoreNodes.getSize();
}
/**
- * Returns the current position within this iterator. The number
- * returned is the 0-based index of the next <code>Row</code> in the iterator,
- * i.e. the one that will be returned on the subsequent <code>next</code> call.
+ * Returns the current position within this iterator. The number returned is
+ * the 0-based index of the next <code>Row</code> in the iterator, i.e. the
+ * one that will be returned on the subsequent <code>next</code> call.
* <p/>
- * Note that this method does not check if there is a next element,
- * i.e. an empty iterator will always return 0.
- *
+ * Note that this method does not check if there is a next element, i.e. an
+ * empty iterator will always return 0.
+ *
* @return the current position withing this iterator.
*/
public long getPosition() {
- return scoreNodes.getPosition();
+ return scoreNodes.getPosition();
}
/**
- * @throws UnsupportedOperationException always.
+ * @throws UnsupportedOperationException
+ * always.
*/
public void remove() {
- throw new UnsupportedOperationException("remove");
+ throw new UnsupportedOperationException("remove");
}
/**
* Returns <code>true</code> if the iteration has more <code>Row</code>s.
* (In other words, returns <code>true</code> if <code>next</code> would
* return an <code>Row</code> rather than throwing an exception.)
- *
+ *
* @return <code>true</code> if the iterator has more elements.
*/
public boolean hasNext() {
- return scoreNodes.hasNext();
+ return scoreNodes.hasNext();
}
/**
* Returns the next <code>Row</code> in the iteration.
- *
+ *
* @return the next <code>Row</code> in the iteration.
- * @throws NoSuchElementException if iteration has no more <code>Row</code>s.
+ * @throws NoSuchElementException
+ * if iteration has no more <code>Row</code>s.
*/
public Object next() throws NoSuchElementException {
- return nextRow();
+ return nextRow();
}
- //---------------------< class RowImpl >------------------------------------
+ // ---------------------< class RowImpl
+ // >------------------------------------
/**
- * Implements the {@link javax.jcr.query.Row} interface, which represents
- * a row in the query result.
+ * Implements the {@link javax.jcr.query.Row} interface, which represents a
+ * row in the query result.
*/
class RowImpl implements Row {
- /**
- * The score for this result row
- */
- private final float score;
+ /**
+ * The score for this result row
+ */
+ private final float score;
- /**
- * The underlying <code>Node</code> of this result row.
- */
- private NodeImpl node;
+ /**
+ * The underlying <code>Node</code> of this result row.
+ */
+ private NodeImpl node;
- /**
- * The score nodes associated with this row.
- */
- private final ScoreNode[] sn;
+ /**
+ * The score nodes associated with this row.
+ */
+ private final ScoreNode[] sn;
- /**
- * Cached value array for returned by {@link #getValues()}.
- */
- private Value[] values;
+ /**
+ * Cached value array for returned by {@link #getValues()}.
+ */
+ private Value[] values;
- /**
- * Creates a new <code>RowImpl</code> instance based on <code>node</code>.
- *
- * @param sn the score nodes associated with this row.
- */
- RowImpl(ScoreNode[] sn) {
- this.sn = sn;
- this.score = sn[0].getScore();
- }
+ /**
+ * Creates a new <code>RowImpl</code> instance based on
+ * <code>node</code>.
+ *
+ * @param sn
+ * the score nodes associated with this row.
+ */
+ RowImpl(ScoreNode[] sn) {
+ this.sn = sn;
+ this.score = sn[0].getScore();
+ }
- /**
- * Returns an array of all the values in the same order as the property
- * names (column names) returned by
- * {@link javax.jcr.query.QueryResult#getColumnNames()}.
- *
- * @return a <code>Value</code> array.
- * @throws RepositoryException if an error occurs while retrieving the
- * values from the <code>Node</code>.
- */
- public Value[] getValues() throws RepositoryException {
- if (values == null)
- {
- Value[] tmp = new Value[properties.length];
- for (int i = 0; i < properties.length; i++)
- {
- String propertyName = resolver.createJCRName(properties[i]).getAsString();
- node = (NodeImpl)getNode();
- if (node.hasProperty(propertyName))
- {
- PropertyImpl prop = (PropertyImpl)node.getProperty(propertyName);
- if (!prop.getDefinition().isMultiple())
- {
- if (prop.getDefinition().getRequiredType() == PropertyType.UNDEFINED)
- {
- tmp[i] = valueFactory.createValue(prop.getString());
- }
- else
- {
- tmp[i] = prop.getValue();
- }
- }
- else
- {
- // mvp values cannot be returned
- tmp[i] = null;
- }
- }
- else
- {
- // property not set or one of the following:
- // jcr:path / jcr:score / rep:excerpt / rep:spellcheck
- if (Constants.JCR_PATH.equals(properties[i]))
- {
- tmp[i] = valueFactory.createValue(node.getPath(), PropertyType.PATH);
- }
- else if (Constants.JCR_SCORE.equals(properties[i]))
- {
- tmp[i] = valueFactory.createValue(Math.round(score * 1000f));
- }
- else if (isExcerptFunction(properties[i]))
- {
- tmp[i] = getExcerpt();
- }
- else if (isSpellCheckFunction(properties[i]))
- {
- tmp[i] = getSpellCheckedStatement();
- }
- else
- {
- tmp[i] = null;
- }
- }
- }
- values = tmp;
- }
- // return a copy of the array
- Value[] ret = new Value[values.length];
- System.arraycopy(values, 0, ret, 0, values.length);
- return ret;
- }
+ /**
+ * Returns an array of all the values in the same order as the property
+ * names (column names) returned by
+ * {@link javax.jcr.query.QueryResult#getColumnNames()}.
+ *
+ * @return a <code>Value</code> array.
+ * @throws RepositoryException
+ * if an error occurs while retrieving the values from the
+ * <code>Node</code>.
+ */
+ public Value[] getValues() throws RepositoryException {
+ if (values == null) {
+ Value[] tmp = new Value[properties.length];
+ for (int i = 0; i < properties.length; i++) {
+ String propertyName = resolver.createJCRName(properties[i])
+ .getAsString();
+ node = (NodeImpl) getNode();
+ if (node.hasProperty(propertyName)) {
+ PropertyImpl prop = (PropertyImpl) node
+ .getProperty(propertyName);
+ if (!prop.getDefinition().isMultiple()) {
+ if (prop.getDefinition().getRequiredType() == PropertyType.UNDEFINED) {
+ tmp[i] = valueFactory.createValue(prop
+ .getString());
+ } else {
+ tmp[i] = prop.getValue();
+ }
+ } else {
+ // mvp values cannot be returned
+ tmp[i] = null;
+ }
+ } else {
+ // property not set or one of the following:
+ // jcr:path / jcr:score / rep:excerpt / rep:spellcheck
+ if (Constants.JCR_PATH.equals(properties[i])) {
+ tmp[i] = valueFactory.createValue(node.getPath(),
+ PropertyType.PATH);
+ } else if (Constants.JCR_SCORE.equals(properties[i])) {
+ tmp[i] = valueFactory.createValue(Math
+ .round(score * 1000f));
+ } else if (isExcerptFunction(properties[i])) {
+ tmp[i] = getExcerpt();
+ } else if (isSpellCheckFunction(properties[i])) {
+ tmp[i] = getSpellCheckedStatement();
+ } else {
+ tmp[i] = null;
+ }
+ }
+ }
+ values = tmp;
+ }
+ // return a copy of the array
+ Value[] ret = new Value[values.length];
+ System.arraycopy(values, 0, ret, 0, values.length);
+ return ret;
+ }
- /**
- * Returns the value of the indicated property in this <code>Row</code>.
- * <p/>
- * If <code>propertyName</code> is not among the column names of the
- * query result table, an <code>ItemNotFoundException</code> is thrown.
- *
- * @return a <code>Value</code>
- * @throws ItemNotFoundException if <code>propertyName</code> is not
- * among the column names of the query result table.
- * @throws RepositoryException if <code>propertyName</code> is not a
- * valid property name.
- */
- public Value getValue(String propertyName) throws ItemNotFoundException, RepositoryException {
- if (propertySet == null) {
- // create the set first
- Set tmp = new HashSet();
- tmp.addAll(Arrays.asList(properties));
- propertySet = tmp;
- }
- try {
- InternalQName prop = resolver.parseJCRName(propertyName).getInternalName();
- if (!propertySet.contains(prop)) {
- if (isExcerptFunction(propertyName)) {
- // excerpt function with parameter
- return getExcerpt(propertyName);
- } else {
- throw new ItemNotFoundException(propertyName);
- }
- }
- if (Constants.JCR_PATH.equals(prop)) {
- //QValue p = QVALUE_FACTORY.create(hmgr.getPath(sn[0].getNodeId()));
- ItemData item = itemMgr.getItemData(sn[0].getNodeId());
- if(item == null)
- throw new ItemNotFoundException(sn[0].getNodeId());
- String path = resolver.createJCRPath(item.getQPath()).getAsString(false);
- return valueFactory.createValue(path, PropertyType.PATH);
- } else if (getNodeImpl().hasProperty(propertyName)) {
- Property p = getNodeImpl().getProperty(propertyName);
- if (p.getDefinition().getRequiredType() == PropertyType.UNDEFINED) {
- return valueFactory.createValue(p.getString());
- } else {
- return p.getValue();
- }
- } else {
-
-
- // either jcr:score, rep:excerpt,
- // rep:spellcheck or not set
- if (Constants.JCR_SCORE.equals(prop)) {
- return valueFactory.createValue(Math.round(score * 1000f));
- } else if (isExcerptFunction(prop)) {
- return getExcerpt();
- } else if (isSpellCheckFunction(prop)) {
- return getSpellCheckedStatement();
- } else {
- return null;
- }
- }
- } catch (RepositoryException e) {
- if (isExcerptFunction(propertyName)) {
- // excerpt function with parameter
- return getExcerpt(propertyName);
- } else {
- throw new RepositoryException(e.getMessage(), e);
- }
- }
- }
+ /**
+ * Returns the value of the indicated property in this <code>Row</code>.
+ * <p/>
+ * If <code>propertyName</code> is not among the column names of the
+ * query result table, an <code>ItemNotFoundException</code> is thrown.
+ *
+ * @return a <code>Value</code>
+ * @throws ItemNotFoundException
+ * if <code>propertyName</code> is not among the column
+ * names of the query result table.
+ * @throws RepositoryException
+ * if <code>propertyName</code> is not a valid property
+ * name.
+ */
+ public Value getValue(String propertyName)
+ throws ItemNotFoundException, RepositoryException {
+ if (propertySet == null) {
+ // create the set first
+ Set tmp = new HashSet();
+ tmp.addAll(Arrays.asList(properties));
+ propertySet = tmp;
+ }
+ try {
+ InternalQName prop = resolver.parseJCRName(propertyName)
+ .getInternalName();
+ if (!propertySet.contains(prop)) {
+ if (isExcerptFunction(propertyName)) {
+ // excerpt function with parameter
+ return getExcerpt(propertyName);
+ } else {
+ throw new ItemNotFoundException(propertyName);
+ }
+ }
+ if (Constants.JCR_PATH.equals(prop)) {
+ // QValue p =
+ // QVALUE_FACTORY.create(hmgr.getPath(sn[0].getNodeId()));
+ ItemData item = itemMgr.getItemData(sn[0].getNodeId());
+ if (item == null)
+ throw new ItemNotFoundException(sn[0].getNodeId());
+ String path = resolver.createJCRPath(item.getQPath())
+ .getAsString(false);
+ return valueFactory.createValue(path, PropertyType.PATH);
+ } else if (getNodeImpl().hasProperty(propertyName)) {
+ Property p = getNodeImpl().getProperty(propertyName);
+ if (p.getDefinition().getRequiredType() == PropertyType.UNDEFINED) {
+ return valueFactory.createValue(p.getString());
+ } else {
+ return p.getValue();
+ }
+ } else {
- /**
- * Returns the <code>Node</code> corresponding to this <code>Row</code>.
- * <p/>
- * A <code>RepositoryException</code> is thrown if this <code>Row</code>
- * contains values from more than one node. This will be the case when more
- * than one selector is included among the columns specified for the query.
- *
- * @return a <code>Node</code>
- * @throws RepositoryException if this query has more than one selector
- * (and therefore, this <code>Row</code> corresponds to more than one
- * <code>Node</code>) or if another error occurs.
- * @since JCR 2.0
- */
- public Node getNode() throws RepositoryException {
- checkSingleSelector("Use getNode(String) instead.");
- return getNodeImpl();
- }
+ // either jcr:score, rep:excerpt,
+ // rep:spellcheck or not set
+ if (Constants.JCR_SCORE.equals(prop)) {
+ return valueFactory.createValue(Math
+ .round(score * 1000f));
+ } else if (isExcerptFunction(prop)) {
+ return getExcerpt();
+ } else if (isSpellCheckFunction(prop)) {
+ return getSpellCheckedStatement();
+ } else {
+ return null;
+ }
+ }
+ } catch (RepositoryException e) {
+ if (isExcerptFunction(propertyName)) {
+ // excerpt function with parameter
+ return getExcerpt(propertyName);
+ } else {
+ throw new RepositoryException(e.getMessage(), e);
+ }
+ }
+ }
- /**
- * Returns the <code>Node</code> corresponding to this <code>Row</code> and
- * the specified selector.
- *
- * @param selectorName a <code>String</code>
- * @return a <code>Node</code>
- * @throws RepositoryException if <code>selectorName</code> is not the alias
- * of a selector in this query or if another error occurs.
- * @since JCR 2.0
- */
- public Node getNode(String selectorName) throws RepositoryException {
- ScoreNode s = sn[getSelectorIndex(selectorName)];
- if (s == null) {
- // TODO correct?
- return null;
- }
- return (Node) itemMgr.getItemByIdentifier(s.getNodeId(),true);
- }
+ /**
+ * Returns the <code>Node</code> corresponding to this <code>Row</code>.
+ * <p/>
+ * A <code>RepositoryException</code> is thrown if this <code>Row</code>
+ * contains values from more than one node. This will be the case when
+ * more than one selector is included among the columns specified for
+ * the query.
+ *
+ * @return a <code>Node</code>
+ * @throws RepositoryException
+ * if this query has more than one selector (and therefore,
+ * this <code>Row</code> corresponds to more than one
+ * <code>Node</code>) or if another error occurs.
+ * @since JCR 2.0
+ */
+ public Node getNode() throws RepositoryException {
+ checkSingleSelector("Use getNode(String) instead.");
+ return getNodeImpl();
+ }
- /**
- * Equivalent to <code>Row.getNode().getPath()</code>. However, some
- * implementations may be able gain efficiency by not resolving the actual
- * <code>Node</code>.
- *
- * @return a <code>String</code>
- * @throws RepositoryException if this query has more than one selector
- * (and therefore, this <code>Row</code> corresponds to more than one
- * <code>Node</code>) or if another error occurs.
- * @since JCR 2.0
- */
- public String getPath() throws RepositoryException {
- checkSingleSelector("Use getPath(String) instead.");
- ItemData item = itemMgr.getItemData(sn[0].getNodeId());
- if(item==null)
- throw new ItemNotFoundException("Item not found "+sn[0].getNodeId());
- return resolver.createJCRPath(item.getQPath()).getAsString(false);
- }
+ /**
+ * Returns the <code>Node</code> corresponding to this <code>Row</code>
+ * and the specified selector.
+ *
+ * @param selectorName
+ * a <code>String</code>
+ * @return a <code>Node</code>
+ * @throws RepositoryException
+ * if <code>selectorName</code> is not the alias of a
+ * selector in this query or if another error occurs.
+ * @since JCR 2.0
+ */
+ public Node getNode(String selectorName) throws RepositoryException {
+ ScoreNode s = sn[getSelectorIndex(selectorName)];
+ if (s == null) {
+ // TODO correct?
+ return null;
+ }
+ return (Node) itemMgr.getItemByIdentifier(s.getNodeId(), true);
+ }
- /**
- * Equivalent to <code>Row.getNode(selectorName).getPath()</code>. However, some
- * implementations may be able gain efficiency by not resolving the actual
- * <code>Node</code>.
- *
- * @param selectorName a <code>String</code>
- * @return a <code>String</code>
- * @throws RepositoryException if <code>selectorName</code> is not the alias
- * of a selector in this query or if another error occurs.
- * @since JCR 2.0
- */
- public String getPath(String selectorName) throws RepositoryException {
- Node n = getNode(selectorName);
- if (n != null) {
- return n.getPath();
- } else {
- return null;
- }
- }
+ /**
+ * Equivalent to <code>Row.getNode().getPath()</code>. However, some
+ * implementations may be able gain efficiency by not resolving the
+ * actual <code>Node</code>.
+ *
+ * @return a <code>String</code>
+ * @throws RepositoryException
+ * if this query has more than one selector (and therefore,
+ * this <code>Row</code> corresponds to more than one
+ * <code>Node</code>) or if another error occurs.
+ * @since JCR 2.0
+ */
+ public String getPath() throws RepositoryException {
+ checkSingleSelector("Use getPath(String) instead.");
+ ItemData item = itemMgr.getItemData(sn[0].getNodeId());
+ if (item == null)
+ throw new ItemNotFoundException("Item not found "
+ + sn[0].getNodeId());
+ return resolver.createJCRPath(item.getQPath()).getAsString(false);
+ }
- /**
- * Returns the full text search score for this row associated with the
- * default selector. This corresponds to the score of a particular node.
- * <p/>
- * If no <code>FullTextSearchScore</code> AQM object is associated with the
- * default selector this method will still return a value. However, in that
- * case the returned value may not be meaningful or may simply reflect the
- * minimum possible relevance level (for example, in some systems this might
- * be a score of 0).
- * <p/>
- * Note, in JCR-SQL2 a <code>FullTextSearchScore</code> AQM object is represented
- * by a <code>SCORE()</code> function. In JCR-JQOM it is represented by a
- * Java object of type <code>javax.jcr.query.qom.FullTextSearchScore</code>.
- *
- * @return a <code>double</code>
- * @throws RepositoryException if this query has more than one selector
- * (and therefore, this <code>Row</code> corresponds to more than one
- * <code>Node</code>) or if another error occurs.
- * @since JCR 2.0
- */
- public double getScore() throws RepositoryException {
- checkSingleSelector("Use getScore(String) instead.");
- return score;
- }
+ /**
+ * Equivalent to <code>Row.getNode(selectorName).getPath()</code>.
+ * However, some implementations may be able gain efficiency by not
+ * resolving the actual <code>Node</code>.
+ *
+ * @param selectorName
+ * a <code>String</code>
+ * @return a <code>String</code>
+ * @throws RepositoryException
+ * if <code>selectorName</code> is not the alias of a
+ * selector in this query or if another error occurs.
+ * @since JCR 2.0
+ */
+ public String getPath(String selectorName) throws RepositoryException {
+ Node n = getNode(selectorName);
+ if (n != null) {
+ return n.getPath();
+ } else {
+ return null;
+ }
+ }
- /**
- * Returns the full text search score for this row associated with the
- * specified selector. This corresponds to the score of a particular node.
- * <p/>
- * If no <code>FullTextSearchScore</code> AQM object is associated with the
- * selector <code>selectorName</code> this method will still return a value.
- * However, in that case the returned value may not be meaningful or may
- * simply reflect the minimum possible relevance level (for example, in some
- * systems this might be a score of 0).
- * <p/>
- * Note, in JCR-SQL2 a <code>FullTextSearchScore</code> AQM object is represented
- * by a <code>SCORE()</code> function. In JCR-JQOM it is represented by a
- * Java object of type <code>javax.jcr.query.qom.FullTextSearchScore</code>.
- *
- * @param selectorName a <code>String</code>
- * @return a <code>String</code>
- * @throws RepositoryException if <code>selectorName</code> is not the alias
- * of a selector in this query or if another error occurs.
- * @since JCR 2.0
- */
- public double getScore(String selectorName) throws RepositoryException {
- ScoreNode s = sn[getSelectorIndex(selectorName)];
- if (s == null) {
- // TODO correct?
- return Double.NaN;
- }
- return s.getScore();
- }
+ /**
+ * Returns the full text search score for this row associated with the
+ * default selector. This corresponds to the score of a particular node.
+ * <p/>
+ * If no <code>FullTextSearchScore</code> AQM object is associated with
+ * the default selector this method will still return a value. However,
+ * in that case the returned value may not be meaningful or may simply
+ * reflect the minimum possible relevance level (for example, in some
+ * systems this might be a score of 0).
+ * <p/>
+ * Note, in JCR-SQL2 a <code>FullTextSearchScore</code> AQM object is
+ * represented by a <code>SCORE()</code> function. In JCR-JQOM it is
+ * represented by a Java object of type
+ * <code>javax.jcr.query.qom.FullTextSearchScore</code>.
+ *
+ * @return a <code>double</code>
+ * @throws RepositoryException
+ * if this query has more than one selector (and therefore,
+ * this <code>Row</code> corresponds to more than one
+ * <code>Node</code>) or if another error occurs.
+ * @since JCR 2.0
+ */
+ public double getScore() throws RepositoryException {
+ checkSingleSelector("Use getScore(String) instead.");
+ return score;
+ }
- //-----------------------------< internal >-----------------------------
+ /**
+ * Returns the full text search score for this row associated with the
+ * specified selector. This corresponds to the score of a particular
+ * node.
+ * <p/>
+ * If no <code>FullTextSearchScore</code> AQM object is associated with
+ * the selector <code>selectorName</code> this method will still return
+ * a value. However, in that case the returned value may not be
+ * meaningful or may simply reflect the minimum possible relevance level
+ * (for example, in some systems this might be a score of 0).
+ * <p/>
+ * Note, in JCR-SQL2 a <code>FullTextSearchScore</code> AQM object is
+ * represented by a <code>SCORE()</code> function. In JCR-JQOM it is
+ * represented by a Java object of type
+ * <code>javax.jcr.query.qom.FullTextSearchScore</code>.
+ *
+ * @param selectorName
+ * a <code>String</code>
+ * @return a <code>String</code>
+ * @throws RepositoryException
+ * if <code>selectorName</code> is not the alias of a
+ * selector in this query or if another error occurs.
+ * @since JCR 2.0
+ */
+ public double getScore(String selectorName) throws RepositoryException {
+ ScoreNode s = sn[getSelectorIndex(selectorName)];
+ if (s == null) {
+ // TODO correct?
+ return Double.NaN;
+ }
+ return s.getScore();
+ }
- /**
- * Returns the node corresponding to this row.
- *
- * @return the node.
- * @throws RepositoryException if an error occurs while retrieving the
- * node. e.g. node does not exist anymore.
- */
- private NodeImpl getNodeImpl() throws RepositoryException {
- if (node == null) {
- node = (NodeImpl) itemMgr.getItemByIdentifier(sn[0].getNodeId(),true);
- }
- return node;
- }
+ // -----------------------------< internal
+ // >-----------------------------
- /**
- * Checks if there is a single selector and otherwise throws a
- * RepositoryException.
- *
- * @param useInstead message telling, which method to use instead.
- * @throws RepositoryException if there is more than one selector.
- */
- private void checkSingleSelector(String useInstead) throws RepositoryException {
- if (sn.length > 1) {
- String msg = "More than one selector. " + useInstead;
- throw new RepositoryException(msg);
- }
- }
+ /**
+ * Returns the node corresponding to this row.
+ *
+ * @return the node.
+ * @throws RepositoryException
+ * if an error occurs while retrieving the node. e.g. node
+ * does not exist anymore.
+ */
+ private NodeImpl getNodeImpl() throws RepositoryException {
+ if (node == null) {
+ node = (NodeImpl) itemMgr.getItemByIdentifier(
+ sn[0].getNodeId(), true);
+ }
+ return node;
+ }
- /**
- * Gets the selector index for the given <code>selectorName</code>.
- *
- * @param selectorName the selector name.
- * @return the selector index.
- * @throws RepositoryException if the selector name is not a valid JCR
- * name or the selector name is not the
- * alias of a selector in this query.
- */
- private int getSelectorIndex(String selectorName)
- throws RepositoryException {
- int idx = selectorNames.indexOf(resolver.parseJCRName(selectorName));
- if (idx == -1) {
- throw new RepositoryException("Unknown selector name: " + selectorName);
- }
- return idx;
- }
+ /**
+ * Checks if there is a single selector and otherwise throws a
+ * RepositoryException.
+ *
+ * @param useInstead
+ * message telling, which method to use instead.
+ * @throws RepositoryException
+ * if there is more than one selector.
+ */
+ private void checkSingleSelector(String useInstead)
+ throws RepositoryException {
+ if (sn.length > 1) {
+ String msg = "More than one selector. " + useInstead;
+ throw new RepositoryException(msg);
+ }
+ }
- /**
- * @param name a Name.
- * @return <code>true</code> if <code>name</code> is the rep:excerpt
- * function, <code>false</code> otherwise.
- */
- private boolean isExcerptFunction(InternalQName name) {
- return name.getNamespace().equals(Constants.NS_REP_URI)
- && name.getName().startsWith(EXCERPT_FUNC_LPAR);
- }
+ /**
+ * Gets the selector index for the given <code>selectorName</code>.
+ *
+ * @param selectorName
+ * the selector name.
+ * @return the selector index.
+ * @throws RepositoryException
+ * if the selector name is not a valid JCR name or the
+ * selector name is not the alias of a selector in this
+ * query.
+ */
+ private int getSelectorIndex(String selectorName)
+ throws RepositoryException {
+ int idx = selectorNames
+ .indexOf(resolver.parseJCRName(selectorName));
+ if (idx == -1) {
+ throw new RepositoryException("Unknown selector name: "
+ + selectorName);
+ }
+ return idx;
+ }
- /**
- * @param name a String.
- * @return <code>true</code> if <code>name</code> is the rep:excerpt
- * function, <code>false</code> otherwise.
- */
- private boolean isExcerptFunction(String name) {
- try {
- return name.startsWith(
- resolver.createJCRName(REP_EXCERPT_LPAR).getAsString());
- } catch (NamespaceException e) {
- // will never happen
- return false;
- }
- catch (RepositoryException e)
- {
- // TODO Auto-generated catch block
- e.printStackTrace();
- return false;
- }
- }
+ /**
+ * @param name
+ * a Name.
+ * @return <code>true</code> if <code>name</code> is the rep:excerpt
+ * function, <code>false</code> otherwise.
+ */
+ private boolean isExcerptFunction(InternalQName name) {
+ return name.getNamespace().equals(Constants.NS_REP_URI)
+ && name.getName().startsWith(EXCERPT_FUNC_LPAR);
+ }
- /**
- * Returns an excerpt for the node associated with this row.
- *
- * @return a StringValue or <code>null</code> if the excerpt cannot be
- * created or an error occurs.
- */
- private Value getExcerpt() {
- return createExcerpt(sn[0].getNodeId());
- }
+ /**
+ * @param name
+ * a String.
+ * @return <code>true</code> if <code>name</code> is the rep:excerpt
+ * function, <code>false</code> otherwise.
+ */
+ private boolean isExcerptFunction(String name) {
+ try {
+ return name.startsWith(resolver.createJCRName(REP_EXCERPT_LPAR)
+ .getAsString());
+ } catch (NamespaceException e) {
+ // will never happen
+ return false;
+ } catch (RepositoryException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ return false;
+ }
+ }
- /**
- * Returns an excerpt for the node indicated by the relative path
- * parameter of the rep:excerpt function. The relative path is resolved
- * against the node associated with this row.
- *
- * @param excerptCall the rep:excerpt function with the parameter as
- * string.
- * @return a StringValue or <code>null</code> if the excerpt cannot be
- * created or an error occurs.
- * @throws RepositoryException if the function call is not well-formed.
- */
- private Value getExcerpt(String excerptCall) throws RepositoryException {
- int idx = excerptCall.indexOf(EXCERPT_FUNC_LPAR);
- int end = excerptCall.lastIndexOf(')');
- if (end == -1) {
- throw new RepositoryException("Missing right parenthesis");
- }
- String pathStr = excerptCall.substring(
- idx + EXCERPT_FUNC_LPAR.length(), end).trim();
- String decodedPath = ISO9075.decode(pathStr);
- try {
- NodeImpl n = (NodeImpl) getNodeImpl().getNode(decodedPath);
- return createExcerpt(n.getData().getIdentifier());
- } catch (PathNotFoundException e) {
- // does not exist or references a property
- try {
- Property p = getNode().getProperty(decodedPath);
- return highlight(p.getValue().getString());
- } catch (PathNotFoundException e1) {
- // does not exist
- return null;
- }
- }
- }
+ /**
+ * Returns an excerpt for the node associated with this row.
+ *
+ * @return a StringValue or <code>null</code> if the excerpt cannot be
+ * created or an error occurs.
+ */
+ private Value getExcerpt() {
+ return createExcerpt(sn[0].getNodeId());
+ }
- /**
- * Creates an excerpt for node with the given <code>id</code>.
- *
- * @return a StringValue or <code>null</code> if the excerpt cannot be
- * created or an error occurs.
- */
- private Value createExcerpt(String id) {
- if (excerptProvider == null) {
- return null;
- }
- try {
- long time = System.currentTimeMillis();
- String excerpt = excerptProvider.getExcerpt(id, 3, 150);
- time = System.currentTimeMillis() - time;
- log.debug("Created excerpt in {} ms.", new Long(time));
- if (excerpt != null) {
- return valueFactory.createValue(excerpt);
- } else {
- return null;
- }
- } catch (IOException e) {
- return null;
- }
- }
+ /**
+ * Returns an excerpt for the node indicated by the relative path
+ * parameter of the rep:excerpt function. The relative path is resolved
+ * against the node associated with this row.
+ *
+ * @param excerptCall
+ * the rep:excerpt function with the parameter as string.
+ * @return a StringValue or <code>null</code> if the excerpt cannot be
+ * created or an error occurs.
+ * @throws RepositoryException
+ * if the function call is not well-formed.
+ */
+ private Value getExcerpt(String excerptCall) throws RepositoryException {
+ int idx = excerptCall.indexOf(EXCERPT_FUNC_LPAR);
+ int end = excerptCall.lastIndexOf(')');
+ if (end == -1) {
+ throw new RepositoryException("Missing right parenthesis");
+ }
+ String pathStr = excerptCall.substring(
+ idx + EXCERPT_FUNC_LPAR.length(), end).trim();
+ String decodedPath = ISO9075.decode(pathStr);
+ try {
+ NodeImpl n = (NodeImpl) getNodeImpl().getNode(decodedPath);
+ return createExcerpt(n.getData().getIdentifier());
+ } catch (PathNotFoundException e) {
+ // does not exist or references a property
+ try {
+ Property p = getNode().getProperty(decodedPath);
+ return highlight(p.getValue().getString());
+ } catch (PathNotFoundException e1) {
+ // does not exist
+ return null;
+ }
+ }
+ }
- /**
- * Highlights the matching terms in the passed <code>text</code>.
- *
- * @return a StringValue or <code>null</code> if highlighting fails.
- */
- private Value highlight(String text) {
- if (!(excerptProvider instanceof HighlightingExcerptProvider)) {
- return null;
- }
- HighlightingExcerptProvider hep =
- (HighlightingExcerptProvider) excerptProvider;
- try {
- long time = System.currentTimeMillis();
- text = hep.highlight(text);
- time = System.currentTimeMillis() - time;
- log.debug("Highlighted text in {} ms.", new Long(time));
- return valueFactory.createValue(text);
- } catch (IOException e) {
- return null;
- }
- }
+ /**
+ * Creates an excerpt for node with the given <code>id</code>.
+ *
+ * @return a StringValue or <code>null</code> if the excerpt cannot be
+ * created or an error occurs.
+ */
+ private Value createExcerpt(String id) {
+ if (excerptProvider == null) {
+ return null;
+ }
+ try {
+ long time = System.currentTimeMillis();
+ String excerpt = excerptProvider.getExcerpt(id, 3, 150);
+ time = System.currentTimeMillis() - time;
+ log.debug("Created excerpt in {} ms.", new Long(time));
+ if (excerpt != null) {
+ return valueFactory.createValue(excerpt);
+ } else {
+ return null;
+ }
+ } catch (IOException e) {
+ return null;
+ }
+ }
- /**
- * @param name a Name.
- * @return <code>true</code> if <code>name</code> is the rep:spellcheck
- * function, <code>false</code> otherwise.
- */
- private boolean isSpellCheckFunction(InternalQName name) {
- return name.getNamespace().equals(Constants.NS_REP_URI)
- && name.getName().startsWith(SPELLCHECK_FUNC_LPAR);
- }
+ /**
+ * Highlights the matching terms in the passed <code>text</code>.
+ *
+ * @return a StringValue or <code>null</code> if highlighting fails.
+ */
+ private Value highlight(String text) {
+ if (!(excerptProvider instanceof HighlightingExcerptProvider)) {
+ return null;
+ }
+ HighlightingExcerptProvider hep = (HighlightingExcerptProvider) excerptProvider;
+ try {
+ long time = System.currentTimeMillis();
+ text = hep.highlight(text);
+ time = System.currentTimeMillis() - time;
+ log.debug("Highlighted text in {} ms.", new Long(time));
+ return valueFactory.createValue(text);
+ } catch (IOException e) {
+ return null;
+ }
+ }
- /**
- * Returns the spell checked string of the first relation query node
- * with a spellcheck operation.
- *
- * @return a StringValue or <code>null</code> if the spell checker
- * thinks the words are spelled correctly. This method also
- * returns <code>null</code> if no spell checker is configured.
- */
- private Value getSpellCheckedStatement() {
- String v = null;
- if (spellSuggestion != null) {
- try {
- v = spellSuggestion.getSuggestion();
- } catch (IOException e) {
- log.warn("Spell checking failed", e);
- }
- }
- if (v != null) {
- return valueFactory.createValue(v);
- } else {
- return null;
- }
- }
+ /**
+ * @param name
+ * a Name.
+ * @return <code>true</code> if <code>name</code> is the rep:spellcheck
+ * function, <code>false</code> otherwise.
+ */
+ private boolean isSpellCheckFunction(InternalQName name) {
+ return name.getNamespace().equals(Constants.NS_REP_URI)
+ && name.getName().startsWith(SPELLCHECK_FUNC_LPAR);
+ }
+
+ /**
+ * Returns the spell checked string of the first relation query node
+ * with a spellcheck operation.
+ *
+ * @return a StringValue or <code>null</code> if the spell checker
+ * thinks the words are spelled correctly. This method also
+ * returns <code>null</code> if no spell checker is configured.
+ */
+ private Value getSpellCheckedStatement() {
+ String v = null;
+ if (spellSuggestion != null) {
+ try {
+ v = spellSuggestion.getSuggestion();
+ } catch (IOException e) {
+ log.warn("Spell checking failed", e);
+ } catch (RepositoryException e) {
+ log.warn("Spell checking failed", e);
+ }
+ }
+ if (v != null) {
+ return valueFactory.createValue(v);
+ } else {
+ return null;
+ }
+ }
}
}
Modified: jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SpellSuggestion.java
===================================================================
--- jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SpellSuggestion.java 2009-10-01 09:14:03 UTC (rev 190)
+++ jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SpellSuggestion.java 2009-10-01 09:18:31 UTC (rev 191)
@@ -16,9 +16,11 @@
*/
package org.exoplatform.services.jcr.impl.core.query.lucene;
+import org.exoplatform.services.jcr.impl.core.query.QueryRootNode;
+
import java.io.IOException;
-import org.exoplatform.services.jcr.impl.core.query.QueryRootNode;
+import javax.jcr.RepositoryException;
/**
* <code>SpellSuggestion</code> implements a spell suggestion, which uses the
@@ -38,28 +40,32 @@
/**
* Creates a new spell suggestion.
- *
- * @param spellChecker the spell checker or <code>null</code> if none is
- * available.
- * @param root the abstract query tree.
+ *
+ * @param spellChecker
+ * the spell checker or <code>null</code> if none is available.
+ * @param root
+ * the abstract query tree.
*/
SpellSuggestion(SpellChecker spellChecker, QueryRootNode root) {
- this.spellChecker = spellChecker;
- this.root = root;
+ this.spellChecker = spellChecker;
+ this.root = root;
}
/**
* @return a suggestion for the spellcheck query node in the abstract query
- * tree passed in the constructor of this <code>SpellSuggestion</code>.
- * This method returns <code>null</code> if the spell checker thinks
- * the spelling is correct or no spell checker was provided.
- * @throws IOException if an error occurs while checking the spelling.
+ * tree passed in the constructor of this
+ * <code>SpellSuggestion</code>. This method returns
+ * <code>null</code> if the spell checker thinks the spelling is
+ * correct or no spell checker was provided.
+ * @throws IOException
+ * if an error occurs while checking the spelling.
+ * @throws RepositoryException
*/
- public String getSuggestion() throws IOException {
- if (spellChecker != null) {
- return spellChecker.check(root);
- } else {
- return null;
- }
+ public String getSuggestion() throws IOException, RepositoryException {
+ if (spellChecker != null) {
+ return spellChecker.check(root);
+ } else {
+ return null;
+ }
}
}
14 years, 7 months
exo-jcr SVN: r190 - in jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene: spell and 1 other directories.
by do-not-reply@jboss.org
Author: skabashnyuk
Date: 2009-10-01 05:14:03 -0400 (Thu, 01 Oct 2009)
New Revision: 190
Added:
jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/spell/
jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/spell/LuceneSpellChecker.java
jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/synonym/
jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/synonym/WordNetSynonyms.java
Modified:
jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SpellChecker.java
Log:
EXOJCR-161 : Spell checker and synonim provider
Modified: jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SpellChecker.java
===================================================================
--- jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SpellChecker.java 2009-10-01 09:01:38 UTC (rev 189)
+++ jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SpellChecker.java 2009-10-01 09:14:03 UTC (rev 190)
@@ -16,23 +16,26 @@
*/
package org.exoplatform.services.jcr.impl.core.query.lucene;
-import java.io.IOException;
-
import org.exoplatform.services.jcr.impl.core.query.QueryHandler;
import org.exoplatform.services.jcr.impl.core.query.QueryRootNode;
+import java.io.IOException;
+
+import javax.jcr.RepositoryException;
+
/**
- * <code>SpellChecker</code> defines an interface to run a spellchecker over
- * a fulltext query statement.
+ * <code>SpellChecker</code> defines an interface to run a spellchecker over a
+ * fulltext query statement.
*/
public interface SpellChecker {
/**
* Initializes this spell checker with an abstract query tree.
- *
- * @param handler the query handler that created this spell checker.
- * @throws IOException if an error occurs while initializing the spell
- * checker.
+ *
+ * @param handler
+ * the query handler that created this spell checker.
+ * @throws IOException
+ * if an error occurs while initializing the spell checker.
*/
void init(QueryHandler handler) throws IOException;
@@ -42,14 +45,16 @@
* spellchecker thinks the words are misspelled. If the spellchecker
* determines that the words are spelled correctly <code>null</code> is
* returned.
- *
- * @param aqt the abstract query tree, which may contain a relation query
+ *
+ * @param aqt
+ * the abstract query tree, which may contain a relation query
* node with a spellcheck operation.
* @return a suggestion or <code>null</code> if this spell checker
* determines that the fulltext query statement is spelled
* correctly.
+ * @throws RepositoryException
*/
- String check(QueryRootNode aqt) throws IOException;
+ String check(QueryRootNode aqt) throws IOException, RepositoryException;
/**
* Closes this spell checker and allows it to free resources.
Added: jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/spell/LuceneSpellChecker.java
===================================================================
--- jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/spell/LuceneSpellChecker.java (rev 0)
+++ jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/spell/LuceneSpellChecker.java 2009-10-01 09:14:03 UTC (rev 190)
@@ -0,0 +1,436 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.exoplatform.services.jcr.impl.core.query.lucene.spell;
+
+import org.apache.lucene.analysis.Token;
+import org.apache.lucene.analysis.TokenStream;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.search.spell.Dictionary;
+import org.apache.lucene.search.spell.LuceneDictionary;
+import org.apache.lucene.search.spell.SpellChecker;
+import org.apache.lucene.store.AlreadyClosedException;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.store.FSDirectory;
+import org.apache.lucene.store.NativeFSLockFactory;
+import org.exoplatform.services.jcr.impl.core.query.QueryHandler;
+import org.exoplatform.services.jcr.impl.core.query.QueryRootNode;
+import org.exoplatform.services.jcr.impl.core.query.RelationQueryNode;
+import org.exoplatform.services.jcr.impl.core.query.TraversingQueryNodeVisitor;
+import org.exoplatform.services.jcr.impl.core.query.lucene.FieldNames;
+import org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.jcr.RepositoryException;
+
+/**
+ * <code>LuceneSpellChecker</code> implements a spell checker based on the terms
+ * present in a lucene index.
+ */
+public class LuceneSpellChecker implements
+ org.exoplatform.services.jcr.impl.core.query.lucene.SpellChecker {
+
+ /**
+ * Logger instance for this class.
+ */
+ private static final Log log = ExoLogger
+ .getLogger(LuceneSpellChecker.class);
+
+ public static final class FiveSecondsRefreshInterval extends
+ LuceneSpellChecker {
+ public FiveSecondsRefreshInterval() {
+ super(5 * 1000);
+ }
+ }
+
+ public static final class OneMinuteRefreshInterval extends
+ LuceneSpellChecker {
+ public OneMinuteRefreshInterval() {
+ super(60 * 1000);
+ }
+ }
+
+ public static final class FiveMinutesRefreshInterval extends
+ LuceneSpellChecker {
+ public FiveMinutesRefreshInterval() {
+ super(5 * 60 * 1000);
+ }
+ }
+
+ public static final class ThirtyMinutesRefreshInterval extends
+ LuceneSpellChecker {
+ public ThirtyMinutesRefreshInterval() {
+ super(30 * 60 * 1000);
+ }
+ }
+
+ public static final class OneHourRefreshInterval extends LuceneSpellChecker {
+ public OneHourRefreshInterval() {
+ super(60 * 60 * 1000);
+ }
+ }
+
+ public static final class SixHoursRefreshInterval extends
+ LuceneSpellChecker {
+ public SixHoursRefreshInterval() {
+ super(6 * 60 * 60 * 1000);
+ }
+ }
+
+ public static final class TwelveHoursRefreshInterval extends
+ LuceneSpellChecker {
+ public TwelveHoursRefreshInterval() {
+ super(12 * 60 * 60 * 1000);
+ }
+ }
+
+ public static final class OneDayRefreshInterval extends LuceneSpellChecker {
+ public OneDayRefreshInterval() {
+ super(24 * 60 * 60 * 1000);
+ }
+ }
+
+ /**
+ * The internal spell checker.
+ */
+ private InternalSpellChecker spellChecker;
+
+ /**
+ * The refresh interval.
+ */
+ private final long refreshInterval;
+
+ /**
+ * Spell checker with a default refresh interval of one hour.
+ */
+ public LuceneSpellChecker() {
+ this(60 * 60 * 1000); // default refresh interval: one hour
+ }
+
+ protected LuceneSpellChecker(long refreshInterval) {
+ this.refreshInterval = refreshInterval;
+ }
+
+ /**
+ * Initializes this spell checker.
+ *
+ * @param handler
+ * the query handler that created this spell checker.
+ * @throws IOException
+ * if <code>handler</code> is not of type {@link SearchIndex}.
+ */
+ public void init(QueryHandler handler) throws IOException {
+ if (handler instanceof SearchIndex) {
+ this.spellChecker = new InternalSpellChecker((SearchIndex) handler);
+ } else {
+ throw new IOException("LuceneSpellChecker only works with "
+ + SearchIndex.class.getName());
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws RepositoryException
+ */
+ public String check(QueryRootNode aqt) throws IOException,
+ RepositoryException {
+ String stmt = getFulltextStatement(aqt);
+ if (stmt == null) {
+ // no spellcheck operation in query
+ return null;
+ }
+ return spellChecker.suggest(stmt);
+ }
+
+ public void close() {
+ spellChecker.close();
+ }
+
+ // ------------------------------< internal
+ // >--------------------------------
+
+ /**
+ * Returns the fulltext statement of a spellcheck relation query node or
+ * <code>null</code> if none exists in the abstract query tree.
+ *
+ * @param aqt
+ * the abstract query tree.
+ * @return the fulltext statement or <code>null</code>.
+ * @throws RepositoryException
+ */
+ private String getFulltextStatement(QueryRootNode aqt)
+ throws RepositoryException {
+ final String[] stmt = new String[1];
+ aqt.accept(new TraversingQueryNodeVisitor() {
+ public Object visit(RelationQueryNode node, Object o)
+ throws RepositoryException {
+ if (stmt[0] == null
+ && node.getOperation() == RelationQueryNode.OPERATION_SPELLCHECK) {
+ stmt[0] = node.getStringValue();
+ }
+ return super.visit(node, o);
+ }
+ }, null);
+ return stmt[0];
+ }
+
+ private final class InternalSpellChecker {
+
+ /**
+ * Timestamp when the last refresh was done.
+ */
+ private long lastRefresh;
+
+ /**
+ * Set to true while a refresh is done in a separate thread.
+ */
+ private boolean refreshing = false;
+
+ /**
+ * The query handler associated with this spell checker.
+ */
+ private final SearchIndex handler;
+
+ /**
+ * The directory where the spell index is stored.
+ */
+ private final Directory spellIndexDirectory;
+
+ /**
+ * The underlying spell checker.
+ */
+ private SpellChecker spellChecker;
+
+ /**
+ * Creates a new internal spell checker.
+ *
+ * @param handler
+ * the associated query handler.
+ */
+ InternalSpellChecker(SearchIndex handler) throws IOException {
+ this.handler = handler;
+ String path = handler.getContext().getIndexDirectory()
+ + File.separatorChar + "spellchecker";
+ this.spellIndexDirectory = FSDirectory.getDirectory(path,
+ new NativeFSLockFactory(path));
+ if (IndexReader.indexExists(spellIndexDirectory)) {
+ this.lastRefresh = System.currentTimeMillis();
+ }
+ this.spellChecker = new SpellChecker(spellIndexDirectory);
+ refreshSpellChecker();
+ }
+
+ /**
+ * Checks a fulltext query statement and suggests a spell checked
+ * version of the statement. If the spell checker thinks the spelling is
+ * correct <code>null</code> is returned.
+ *
+ * @param statement
+ * the fulltext query statement.
+ * @return a suggestion or <code>null</code>.
+ */
+ String suggest(String statement) throws IOException {
+ // tokenize the statement (field name doesn't matter actually...)
+ List<String> words = new ArrayList<String>();
+ List<Token> tokens = new ArrayList<Token>();
+ tokenize(statement, words, tokens);
+
+ String[] suggestions = check(words
+ .toArray(new String[words.size()]));
+ if (suggestions != null) {
+ // replace words in statement in reverse order because length
+ // of statement will change
+ StringBuffer sb = new StringBuffer(statement);
+ for (int i = suggestions.length - 1; i >= 0; i--) {
+ Token t = tokens.get(i);
+ // only replace if word acutally changed
+ if (!t.termText().equalsIgnoreCase(suggestions[i])) {
+ sb.replace(t.startOffset(), t.endOffset(),
+ suggestions[i]);
+ }
+ }
+ return sb.toString();
+ } else {
+ return null;
+ }
+ }
+
+ void close() {
+ try {
+ spellIndexDirectory.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ // urgh, the lucene spell checker cannot be closed explicitly.
+ // finalize will close the reader...
+ spellChecker = null;
+ }
+
+ /**
+ * Tokenizes the statement into words and tokens.
+ *
+ * @param statement
+ * the fulltext query statement.
+ * @param words
+ * this list will be filled with the original words extracted
+ * from the statement.
+ * @param tokens
+ * this list will be filled with the tokens parsed from the
+ * statement.
+ * @throws IOException
+ * if an error occurs while parsing the statement.
+ */
+ private void tokenize(String statement, List<String> words,
+ List<Token> tokens) throws IOException {
+ TokenStream ts = handler.getTextAnalyzer().tokenStream(
+ FieldNames.FULLTEXT, new StringReader(statement));
+ try {
+ Token t;
+ while ((t = ts.next()) != null) {
+ String origWord = statement.substring(t.startOffset(), t
+ .endOffset());
+ if (t.getPositionIncrement() > 0) {
+ words.add(t.termText());
+ tokens.add(t);
+ } else {
+ // very simple implementation: use termText with length
+ // closer to original word
+ Token current = tokens.get(tokens.size() - 1);
+ if (Math.abs(origWord.length()
+ - current.termText().length()) > Math
+ .abs(origWord.length() - t.termText().length())) {
+ // replace current token and word
+ words.set(words.size() - 1, t.termText());
+ tokens.set(tokens.size() - 1, t);
+ }
+ }
+ }
+ } finally {
+ ts.close();
+ }
+ }
+
+ /**
+ * Checks the spelling of the passed <code>words</code> and returns a
+ * suggestion.
+ *
+ * @param words
+ * the words to check.
+ * @return a suggestion of correctly spelled <code>words</code> or
+ * <code>null</code> if this spell checker thinks
+ * <code>words</code> are spelled correctly.
+ * @throws IOException
+ * if an error occurs while spell checking.
+ */
+ private String[] check(String words[]) throws IOException {
+ refreshSpellChecker();
+ boolean hasSuggestion = false;
+ IndexReader reader = handler.getIndexReader();
+ try {
+ for (int retries = 0; retries < 100; retries++) {
+ try {
+ String[] suggestion = new String[words.length];
+ for (int i = 0; i < words.length; i++) {
+ String[] similar = spellChecker.suggestSimilar(
+ words[i], 5, reader, FieldNames.FULLTEXT,
+ true);
+ if (similar.length > 0) {
+ suggestion[i] = similar[0];
+ hasSuggestion = true;
+ } else {
+ suggestion[i] = words[i];
+ }
+ }
+ if (hasSuggestion) {
+ log.debug("Successful after "
+ + new Integer(retries) + " retries");
+ return suggestion;
+ } else {
+ return null;
+ }
+ } catch (AlreadyClosedException e) {
+ // it may happen that the index reader inside the
+ // spell checker is closed while searching for
+ // suggestions. this is actually a design flaw in the
+ // lucene spell checker, but for now we simply retry
+ }
+ }
+ // unsuccessful after retries
+ return null;
+ } finally {
+ reader.close();
+ }
+ }
+
+ /**
+ * Refreshes the underlying spell checker in a background thread.
+ * Synchronization is done on this <code>LuceneSpellChecker</code>
+ * instance. While the refresh takes place {@link #refreshing} is set to
+ * <code>true</code>.
+ */
+ private void refreshSpellChecker() {
+ if (lastRefresh + refreshInterval < System.currentTimeMillis()) {
+ synchronized (this) {
+ if (refreshing) {
+ return;
+ } else {
+ refreshing = true;
+ Runnable refresh = new Runnable() {
+ public void run() {
+ try {
+ IndexReader reader = handler
+ .getIndexReader();
+ try {
+ long time = System.currentTimeMillis();
+ Dictionary dict = new LuceneDictionary(
+ reader, FieldNames.FULLTEXT);
+ log
+ .debug("Starting spell checker index refresh");
+ spellChecker.indexDictionary(dict);
+ time = System.currentTimeMillis()
+ - time;
+ time = time / 1000;
+ log
+ .info("Spell checker index refreshed in: "
+ + new Long(time)
+ + " s.");
+ } finally {
+ reader.close();
+ synchronized (InternalSpellChecker.this) {
+ refreshing = false;
+ }
+ }
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ };
+ new Thread(refresh, "SpellChecker Refresh").start();
+ lastRefresh = System.currentTimeMillis();
+ }
+ }
+ }
+ }
+ }
+}
Property changes on: jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/spell/LuceneSpellChecker.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/synonym/WordNetSynonyms.java
===================================================================
--- jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/synonym/WordNetSynonyms.java (rev 0)
+++ jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/synonym/WordNetSynonyms.java 2009-10-01 09:14:03 UTC (rev 190)
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.exoplatform.services.jcr.impl.core.query.lucene.synonym;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.lucene.index.memory.SynonymMap;
+
+import org.exoplatform.services.jcr.impl.core.query.lucene.SynonymProvider;
+
+/**
+ * <code>WordNetSynonyms</code> implements a {@link SynonymProvider} that is backed by the WordNet
+ * prolog file <a href="http://www.cogsci.princeton.edu/2.0/WNprolog-2.0.tar.gz">wn_s.pl</a>.
+ */
+public class WordNetSynonyms implements SynonymProvider
+{
+
+ /**
+ * The synonym map or <code>null</code> if an error occurred while reading the prolog file.
+ */
+ private SynonymMap SYNONYM_MAP;
+
+ /**
+ * {@inheritDoc}
+ */
+ public void initialize(InputStream configuration) throws IOException
+ {
+
+ SynonymMap sm = null;
+ try
+ {
+ sm = new SynonymMap(configuration);
+ }
+ catch (IOException e)
+ {
+ // ignore
+ }
+ SYNONYM_MAP = sm;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String[] getSynonyms(String string)
+ {
+ if (SYNONYM_MAP != null)
+ {
+ return SYNONYM_MAP.getSynonyms(string.toLowerCase());
+ }
+ else
+ {
+ return new String[0];
+ }
+ }
+}
Property changes on: jcr/trunk/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/synonym/WordNetSynonyms.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
14 years, 7 months
exo-jcr SVN: r188 - jcr/trunk/component/core.
by do-not-reply@jboss.org
Author: dkatayev
Date: 2009-10-01 04:14:24 -0400 (Thu, 01 Oct 2009)
New Revision: 188
Removed:
jcr/trunk/component/core/exo.jcr.component.webdav/
Log:
exo.jcr.component.webdav removed
14 years, 7 months