You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by al...@apache.org on 2012/10/31 11:21:38 UTC
svn commit: r1404071 - in /jackrabbit/oak/trunk/oak-core/src:
main/java/org/apache/jackrabbit/oak/plugins/index/
main/java/org/apache/jackrabbit/oak/plugins/index/lucene/
main/java/org/apache/jackrabbit/oak/plugins/index/property/
test/java/org/apache/...
Author: alexparvulescu
Date: Wed Oct 31 10:21:37 2012
New Revision: 1404071
URL: http://svn.apache.org/viewvc?rev=1404071&view=rev
Log:
OAK-394 IndexManagerHook to manage existing indexes
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/CompositeNodeStateDiff.java (with props)
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexDiff.java (with props)
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexHook.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexHookManager.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneEditor.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneHook.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexHook.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexTest.java
Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/CompositeNodeStateDiff.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/CompositeNodeStateDiff.java?rev=1404071&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/CompositeNodeStateDiff.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/CompositeNodeStateDiff.java Wed Oct 31 10:21:37 2012
@@ -0,0 +1,79 @@
+/*
+ * 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.apache.jackrabbit.oak.plugins.index;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStateDiff;
+
+public class CompositeNodeStateDiff implements NodeStateDiff {
+
+ private final List<NodeStateDiff> providers;
+
+ public CompositeNodeStateDiff(List<NodeStateDiff> providers) {
+ this.providers = providers;
+ }
+
+ public CompositeNodeStateDiff(NodeStateDiff... providers) {
+ this(Arrays.asList(providers));
+ }
+
+ @Override
+ public void propertyAdded(PropertyState after) {
+ for (NodeStateDiff d : providers) {
+ d.propertyAdded(after);
+ }
+ }
+
+ @Override
+ public void propertyChanged(PropertyState before, PropertyState after) {
+ for (NodeStateDiff d : providers) {
+ d.propertyChanged(before, after);
+ }
+ }
+
+ @Override
+ public void propertyDeleted(PropertyState before) {
+ for (NodeStateDiff d : providers) {
+ d.propertyDeleted(before);
+ }
+ }
+
+ @Override
+ public void childNodeAdded(String name, NodeState after) {
+ for (NodeStateDiff d : providers) {
+ d.childNodeAdded(name, after);
+ }
+ }
+
+ @Override
+ public void childNodeChanged(String name, NodeState before, NodeState after) {
+ for (NodeStateDiff d : providers) {
+ d.childNodeChanged(name, before, after);
+ }
+ }
+
+ @Override
+ public void childNodeDeleted(String name, NodeState before) {
+ for (NodeStateDiff d : providers) {
+ d.childNodeDeleted(name, before);
+ }
+ }
+}
Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/CompositeNodeStateDiff.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexHook.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexHook.java?rev=1404071&r1=1404070&r2=1404071&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexHook.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexHook.java Wed Oct 31 10:21:37 2012
@@ -16,13 +16,20 @@
*/
package org.apache.jackrabbit.oak.plugins.index;
-import org.apache.jackrabbit.oak.spi.commit.CommitHook;
+import java.io.Closeable;
+
+import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.spi.state.NodeStateDiff;
/**
* Represents the content of a QueryIndex as well as a mechanism for keeping
* this content up to date.
*
*/
-public interface IndexHook extends CommitHook {
+public interface IndexHook extends Closeable {
+
+ NodeStateDiff preProcess() throws CommitFailedException;
+
+ void postProcess() throws CommitFailedException;
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexHookManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexHookManager.java?rev=1404071&r1=1404070&r2=1404071&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexHookManager.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexHookManager.java Wed Oct 31 10:21:37 2012
@@ -24,6 +24,8 @@ import static org.apache.jackrabbit.oak.
import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.TYPE_UNKNOWN;
import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.REINDEX_PROPERTY_NAME;
+import java.io.IOException;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -64,9 +66,8 @@ public class IndexHookManager implements
// <path>, <builder>
Map<String, NodeBuilder> allDefs = new HashMap<String, NodeBuilder>();
-
- IndexDefDiff diff = new IndexDefDiff(builder, allDefs);
- after.compareAgainstBaseState(before, diff);
+ after.compareAgainstBaseState(before,
+ new IndexDefDiff(builder, allDefs));
// <type, <<path>, <builder>>
Map<String, Map<String, NodeBuilder>> updates = new HashMap<String, Map<String, NodeBuilder>>();
@@ -86,26 +87,54 @@ public class IndexHookManager implements
}
// commit
+ List<IndexHook> hooks = new ArrayList<IndexHook>();
+ List<IndexHook> reindexHooks = new ArrayList<IndexHook>();
+
for (String type : updates.keySet()) {
Map<String, NodeBuilder> update = updates.get(type);
for (String path : update.keySet()) {
NodeBuilder updateBuiler = update.get(path);
boolean reindex = getAndResetReindex(updateBuiler);
- List<? extends IndexHook> hooks = provider.getIndexHooks(type,
- updateBuiler);
- for (IndexHook hook : hooks) {
- if (reindex) {
- hook.processCommit(MemoryNodeState.EMPTY_NODE, after);
- } else {
- hook.processCommit(before, after);
- }
+ if (reindex) {
+ reindexHooks.addAll(provider.getIndexHooks(type,
+ updateBuiler));
+ } else {
+ hooks.addAll(provider.getIndexHooks(type, updateBuiler));
}
-
}
}
+ processIndexHooks(reindexHooks, MemoryNodeState.EMPTY_NODE, after);
+ processIndexHooks(hooks, before, after);
return builder.getNodeState();
}
+ private void processIndexHooks(List<IndexHook> hooks, NodeState before,
+ NodeState after) throws CommitFailedException {
+ try {
+
+ List<NodeStateDiff> diffs = new ArrayList<NodeStateDiff>();
+ for (IndexHook hook : hooks) {
+ diffs.add(hook.preProcess());
+ }
+ after.compareAgainstBaseState(before, new CompositeNodeStateDiff(
+ diffs));
+ for (IndexHook hook : hooks) {
+ hook.postProcess();
+ }
+
+ } finally {
+ for (IndexHook hook : hooks) {
+ try {
+ hook.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ throw new CommitFailedException(
+ "Failed to close the index hook", e);
+ }
+ }
+ }
+ }
+
protected static boolean getAndResetReindex(NodeBuilder builder) {
boolean isReindex = false;
PropertyState ps = builder.getProperty(REINDEX_PROPERTY_NAME);
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneEditor.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneEditor.java?rev=1404071&r1=1404070&r2=1404071&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneEditor.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneEditor.java Wed Oct 31 10:21:37 2012
@@ -16,41 +16,26 @@
*/
package org.apache.jackrabbit.oak.plugins.index.lucene;
-import static org.apache.jackrabbit.oak.commons.PathUtils.concat;
-import static org.apache.jackrabbit.oak.plugins.index.lucene.FieldFactory.newPathField;
-import static org.apache.jackrabbit.oak.plugins.index.lucene.FieldFactory.newPropertyField;
-import static org.apache.jackrabbit.oak.plugins.index.lucene.TermFactory.newPathTerm;
+import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
import java.io.IOException;
-import javax.jcr.PropertyType;
-
-import org.apache.jackrabbit.oak.api.Blob;
import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.Type;
-import org.apache.jackrabbit.oak.spi.commit.CommitHook;
-import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
+import org.apache.jackrabbit.oak.plugins.index.IndexHook;
import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
-import org.apache.jackrabbit.oak.spi.state.NodeState;
import org.apache.jackrabbit.oak.spi.state.NodeStateDiff;
-import org.apache.jackrabbit.oak.spi.state.NodeStateUtils;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
-import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
-import org.apache.lucene.store.Directory;
import org.apache.lucene.util.Version;
-import org.apache.tika.Tika;
-import org.apache.tika.exception.TikaException;
/**
* This class updates a Lucene index when node content is changed.
*/
-class LuceneEditor implements CommitHook, LuceneIndexConstants {
-
- private static final Tika TIKA = new Tika();
+class LuceneEditor implements IndexHook, LuceneIndexConstants {
private static final Version VERSION = Version.LUCENE_40;
@@ -58,6 +43,8 @@ class LuceneEditor implements CommitHook
private static final IndexWriterConfig config = getIndexWriterConfig();
+ private LuceneIndexDiff diff;
+
private static IndexWriterConfig getIndexWriterConfig() {
// FIXME: Hack needed to make Lucene work in an OSGi environment
Thread thread = Thread.currentThread();
@@ -76,167 +63,62 @@ class LuceneEditor implements CommitHook
this.root = root;
}
+ // -----------------------------------------------------< IndexHook >--
+
@Override
- public NodeState processCommit(NodeState before, NodeState after)
- throws CommitFailedException {
- Directory directory = new ReadWriteOakDirectory(
- root.child(INDEX_DATA_CHILD_NAME));
+ public NodeStateDiff preProcess() throws CommitFailedException {
try {
- IndexWriter writer = new IndexWriter(directory, config);
- try {
- LuceneDiff diff = new LuceneDiff(writer, "/");
- after.compareAgainstBaseState(before, diff);
- diff.postProcess(after);
- } finally {
- writer.close();
- }
- return after;
+ IndexWriter writer = new IndexWriter(new ReadWriteOakDirectory(
+ getIndexNode(root).child(INDEX_DATA_CHILD_NAME)), config);
+ diff = new LuceneIndexDiff(writer, root, "/");
+ return diff;
} catch (IOException e) {
e.printStackTrace();
throw new CommitFailedException(
- "Failed to update the full text search index", e);
+ "Failed to create writer for the full text search index", e);
}
}
- private static class LuceneDiff implements NodeStateDiff {
-
- private final IndexWriter writer;
-
- private final String path;
-
- private boolean modified;
-
- private IOException exception;
-
- public LuceneDiff(IndexWriter writer, String path) {
- this.writer = writer;
- this.path = path;
- }
-
- public void postProcess(NodeState state) throws IOException {
- if (exception != null) {
- throw exception;
- }
- if (modified) {
- writer.updateDocument(newPathTerm(path),
- makeDocument(path, state));
- }
- }
-
- @Override
- public void propertyAdded(PropertyState after) {
- modified = true;
- }
-
- @Override
- public void propertyChanged(PropertyState before, PropertyState after) {
- modified = true;
- }
-
- @Override
- public void propertyDeleted(PropertyState before) {
- modified = true;
- }
-
- @Override
- public void childNodeAdded(String name, NodeState after) {
- if (NodeStateUtils.isHidden(name)) {
- return;
- }
- if (exception == null) {
- try {
- addSubtree(concat(path, name), after);
- } catch (IOException e) {
- exception = e;
- }
- }
- }
-
- private void addSubtree(String path, NodeState state)
- throws IOException {
- writer.updateDocument(newPathTerm(path), makeDocument(path, state));
- for (ChildNodeEntry entry : state.getChildNodeEntries()) {
- if (NodeStateUtils.isHidden(entry.getName())) {
- continue;
- }
- addSubtree(concat(path, entry.getName()), entry.getNodeState());
- }
- }
-
- @Override
- public void childNodeChanged(String name, NodeState before,
- NodeState after) {
- if (NodeStateUtils.isHidden(name)) {
- return;
- }
- if (exception == null) {
- try {
- LuceneDiff diff = new LuceneDiff(writer, concat(path, name));
- after.compareAgainstBaseState(before, diff);
- diff.postProcess(after);
- } catch (IOException e) {
- exception = e;
- }
- }
- }
-
- @Override
- public void childNodeDeleted(String name, NodeState before) {
- if (NodeStateUtils.isHidden(name)) {
- return;
- }
- if (exception == null) {
- try {
- deleteSubtree(concat(path, name), before);
- } catch (IOException e) {
- exception = e;
+ private static NodeBuilder getIndexNode(NodeBuilder node) {
+ if (node != null && node.hasChildNode(INDEX_DEFINITIONS_NAME)) {
+ NodeBuilder index = node.child(INDEX_DEFINITIONS_NAME);
+ for (String indexName : index.getChildNodeNames()) {
+ NodeBuilder child = index.child(indexName);
+ if (isIndexNodeType(child.getProperty(JCR_PRIMARYTYPE))
+ && isIndexType(child.getProperty(TYPE_PROPERTY_NAME),
+ TYPE_LUCENE)) {
+ return child;
}
}
}
+ // did not find a proper child, will use root directly
+ return node;
+ }
- private void deleteSubtree(String path, NodeState state)
- throws IOException {
- writer.deleteDocuments(newPathTerm(path));
- for (ChildNodeEntry entry : state.getChildNodeEntries()) {
- if (NodeStateUtils.isHidden(entry.getName())) {
- continue;
- }
- deleteSubtree(concat(path, entry.getName()),
- entry.getNodeState());
- }
- }
+ private static boolean isIndexNodeType(PropertyState ps) {
+ return ps != null && !ps.isArray()
+ && ps.getValue(Type.STRING).equals(INDEX_DEFINITIONS_NODE_TYPE);
+ }
- private static Document makeDocument(String path, NodeState state) {
- Document document = new Document();
- document.add(newPathField(path));
- for (PropertyState property : state.getProperties()) {
- String pname = property.getName();
- switch (property.getType().tag()) {
- case PropertyType.BINARY:
- for (Blob v : property.getValue(Type.BINARIES)) {
- document.add(newPropertyField(pname,
- parseStringValue(v)));
- }
- break;
- default:
- for (String v : property.getValue(Type.STRINGS)) {
- document.add(newPropertyField(pname, v));
- }
- break;
- }
- }
- return document;
- }
+ private static boolean isIndexType(PropertyState ps, String type) {
+ return ps != null && !ps.isArray()
+ && ps.getValue(Type.STRING).equals(type);
+ }
- private static String parseStringValue(Blob v) {
- try {
- return TIKA.parseToString(v.getNewStream());
- } catch (IOException e) {
- } catch (TikaException e) {
- }
- return "";
+ @Override
+ public void postProcess() throws CommitFailedException {
+ try {
+ diff.postProcess();
+ } catch (IOException e) {
+ e.printStackTrace();
+ throw new CommitFailedException(
+ "Failed to update the full text search index", e);
}
-
}
+ @Override
+ public void close() throws IOException {
+ diff.close();
+ diff = null;
+ }
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneHook.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneHook.java?rev=1404071&r1=1404070&r2=1404071&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneHook.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneHook.java Wed Oct 31 10:21:37 2012
@@ -16,10 +16,14 @@
*/
package org.apache.jackrabbit.oak.plugins.index.lucene;
+import java.io.IOException;
+
+import javax.annotation.Nonnull;
+
import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.plugins.index.IndexHook;
import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
-import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStateDiff;
/**
* {@link IndexHook} implementation that is responsible for keeping the
@@ -32,15 +36,34 @@ public class LuceneHook implements Index
private final NodeBuilder builder;
+ private IndexHook luceneEditor;
+
public LuceneHook(NodeBuilder builder) {
this.builder = builder;
}
+ // -----------------------------------------------------< IndexHook >--
+
@Override
- public NodeState processCommit(NodeState before, NodeState after)
- throws CommitFailedException {
- new LuceneEditor(builder).processCommit(before, after);
- return after;
+ @Nonnull
+ public NodeStateDiff preProcess() throws CommitFailedException {
+ luceneEditor = new LuceneEditor(builder);
+ return luceneEditor.preProcess();
}
+ @Override
+ public void postProcess() throws CommitFailedException {
+ luceneEditor.postProcess();
+ }
+
+ @Override
+ public void close() throws IOException {
+ try {
+ if (luceneEditor != null) {
+ luceneEditor.close();
+ }
+ } finally {
+ luceneEditor = null;
+ }
+ }
}
Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexDiff.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexDiff.java?rev=1404071&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexDiff.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexDiff.java Wed Oct 31 10:21:37 2012
@@ -0,0 +1,191 @@
+/*
+ * 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.apache.jackrabbit.oak.plugins.index.lucene;
+
+import static org.apache.jackrabbit.oak.commons.PathUtils.concat;
+import static org.apache.jackrabbit.oak.plugins.index.lucene.FieldFactory.newPathField;
+import static org.apache.jackrabbit.oak.plugins.index.lucene.FieldFactory.newPropertyField;
+import static org.apache.jackrabbit.oak.plugins.index.lucene.TermFactory.newPathTerm;
+
+import java.io.Closeable;
+import java.io.IOException;
+
+import javax.jcr.PropertyType;
+
+import org.apache.jackrabbit.oak.api.Blob;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStateDiff;
+import org.apache.jackrabbit.oak.spi.state.NodeStateUtils;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.index.IndexWriter;
+import org.apache.tika.Tika;
+import org.apache.tika.exception.TikaException;
+
+public class LuceneIndexDiff implements NodeStateDiff, Closeable {
+
+ private static final Tika TIKA = new Tika();
+
+ private final IndexWriter writer;
+
+ private final NodeBuilder node;
+
+ private final String path;
+
+ private boolean modified;
+
+ private IOException exception;
+
+ public LuceneIndexDiff(IndexWriter writer, NodeBuilder node, String path) {
+ this.writer = writer;
+ this.node = node;
+ this.path = path;
+ }
+
+ public void postProcess() throws IOException {
+ if (exception != null) {
+ throw exception;
+ }
+ if (modified) {
+ writer.updateDocument(newPathTerm(path),
+ makeDocument(path, node.getNodeState()));
+ }
+ }
+
+ // -----------------------------------------------------< NodeStateDiff >--
+
+ @Override
+ public void propertyAdded(PropertyState after) {
+ modified = true;
+ }
+
+ @Override
+ public void propertyChanged(PropertyState before, PropertyState after) {
+ modified = true;
+ }
+
+ @Override
+ public void propertyDeleted(PropertyState before) {
+ modified = true;
+ }
+
+ @Override
+ public void childNodeAdded(String name, NodeState after) {
+ if (NodeStateUtils.isHidden(name)) {
+ return;
+ }
+ if (exception == null) {
+ try {
+ addSubtree(concat(path, name), after);
+ } catch (IOException e) {
+ exception = e;
+ }
+ }
+ }
+
+ private void addSubtree(String path, NodeState state) throws IOException {
+ writer.updateDocument(newPathTerm(path), makeDocument(path, state));
+ for (ChildNodeEntry entry : state.getChildNodeEntries()) {
+ if (NodeStateUtils.isHidden(entry.getName())) {
+ continue;
+ }
+ addSubtree(concat(path, entry.getName()), entry.getNodeState());
+ }
+ }
+
+ @Override
+ public void childNodeChanged(String name, NodeState before, NodeState after) {
+ if (NodeStateUtils.isHidden(name)) {
+ return;
+ }
+ if (exception == null && node.hasChildNode(name)) {
+ LuceneIndexDiff diff = new LuceneIndexDiff(writer,
+ node.child(name), concat(path, name));
+ after.compareAgainstBaseState(before, diff);
+ try {
+ diff.postProcess();
+ } catch (IOException e) {
+ exception = e;
+ }
+ }
+ }
+
+ @Override
+ public void childNodeDeleted(String name, NodeState before) {
+ if (NodeStateUtils.isHidden(name)) {
+ return;
+ }
+ if (exception == null) {
+ try {
+ deleteSubtree(concat(path, name), before);
+ } catch (IOException e) {
+ exception = e;
+ }
+ }
+ }
+
+ private void deleteSubtree(String path, NodeState state) throws IOException {
+ writer.deleteDocuments(newPathTerm(path));
+ for (ChildNodeEntry entry : state.getChildNodeEntries()) {
+ if (NodeStateUtils.isHidden(entry.getName())) {
+ continue;
+ }
+ deleteSubtree(concat(path, entry.getName()), entry.getNodeState());
+ }
+ }
+
+ private static Document makeDocument(String path, NodeState state) {
+ Document document = new Document();
+ document.add(newPathField(path));
+ for (PropertyState property : state.getProperties()) {
+ String pname = property.getName();
+ switch (property.getType().tag()) {
+ case PropertyType.BINARY:
+ for (Blob v : property.getValue(Type.BINARIES)) {
+ document.add(newPropertyField(pname, parseStringValue(v)));
+ }
+ break;
+ default:
+ for (String v : property.getValue(Type.STRINGS)) {
+ document.add(newPropertyField(pname, v));
+ }
+ break;
+ }
+ }
+ return document;
+ }
+
+ private static String parseStringValue(Blob v) {
+ try {
+ return TIKA.parseToString(v.getNewStream());
+ } catch (IOException e) {
+ } catch (TikaException e) {
+ }
+ return "";
+ }
+
+ // -----------------------------------------------------< Closeable >--
+
+ @Override
+ public void close() throws IOException {
+ writer.close();
+ }
+
+}
Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexDiff.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexHook.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexHook.java?rev=1404071&r1=1404070&r2=1404071&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexHook.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexHook.java Wed Oct 31 10:21:37 2012
@@ -16,6 +16,7 @@
*/
package org.apache.jackrabbit.oak.plugins.index.property;
+import java.io.IOException;
import java.util.List;
import java.util.Map;
@@ -24,7 +25,7 @@ import javax.annotation.Nonnull;
import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.plugins.index.IndexHook;
import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
-import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStateDiff;
import com.google.common.collect.Maps;
@@ -37,28 +38,35 @@ import com.google.common.collect.Maps;
*
*/
public class PropertyIndexHook implements IndexHook {
-
+
private final NodeBuilder builder;
+ private Map<String, List<PropertyIndexUpdate>> indexes;
+
public PropertyIndexHook(NodeBuilder builder) {
this.builder = builder;
}
+
+ // -----------------------------------------------------< IndexHook >--
+
@Override @Nonnull
- public NodeState processCommit(NodeState before, NodeState after)
- throws CommitFailedException {
- Map<String, List<PropertyIndexUpdate>> indexes = Maps.newHashMap();
- PropertyIndexDiff diff = new PropertyIndexDiff(builder, indexes);
- after.compareAgainstBaseState(before, diff);
+ public NodeStateDiff preProcess() {
+ indexes = Maps.newHashMap();
+ return new PropertyIndexDiff(builder, indexes);
+ }
+ @Override
+ public void postProcess() throws CommitFailedException {
for (List<PropertyIndexUpdate> updates : indexes.values()) {
for (PropertyIndexUpdate update : updates) {
update.apply();
}
}
-
- return builder.getNodeState();
}
-
+ @Override
+ public void close() throws IOException {
+ indexes = null;
+ }
}
\ No newline at end of file
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexTest.java?rev=1404071&r1=1404070&r2=1404071&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexTest.java Wed Oct 31 10:21:37 2012
@@ -16,12 +16,14 @@
*/
package org.apache.jackrabbit.oak.plugins.index.lucene;
+import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
import org.apache.jackrabbit.oak.plugins.index.IndexDefinition;
import org.apache.jackrabbit.oak.plugins.index.IndexDefinitionImpl;
+import org.apache.jackrabbit.oak.plugins.index.IndexHook;
import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeState;
import org.apache.jackrabbit.oak.query.ast.Operator;
import org.apache.jackrabbit.oak.query.index.FilterImpl;
@@ -40,16 +42,21 @@ public class LuceneIndexTest implements
NodeState root = MemoryNodeState.EMPTY_NODE;
NodeBuilder builder = root.builder();
- NodeBuilder index = builder.child("oak:index").child("lucene");
- IndexDefinition testDef = new IndexDefinitionImpl("lucene",
- TYPE_LUCENE, "/oak:index/lucene");
+ builder.child("oak:index").child("lucene")
+ .setProperty(JCR_PRIMARYTYPE, INDEX_DEFINITIONS_NODE_TYPE)
+ .setProperty("type", TYPE_LUCENE);
NodeState before = builder.getNodeState();
builder.setProperty("foo", "bar");
NodeState after = builder.getNodeState();
- new LuceneHook(index).processCommit(before, after);
+ IndexHook l = new LuceneHook(builder);
+ after.compareAgainstBaseState(before, l.preProcess());
+ l.postProcess();
+ l.close();
+ IndexDefinition testDef = new IndexDefinitionImpl("lucene",
+ TYPE_LUCENE, "/oak:index/lucene");
QueryIndex queryIndex = new LuceneIndex(testDef);
FilterImpl filter = new FilterImpl(null);
filter.restrictPath("/", Filter.PathRestriction.EXACT);
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexTest.java?rev=1404071&r1=1404070&r2=1404071&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexTest.java Wed Oct 31 10:21:37 2012
@@ -20,6 +20,7 @@ import java.util.Arrays;
import com.google.common.collect.ImmutableSet;
import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.plugins.index.IndexHook;
import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeState;
import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
import org.apache.jackrabbit.oak.spi.state.NodeState;
@@ -62,8 +63,12 @@ public class PropertyIndexTest {
withoutIndex = System.nanoTime() - withoutIndex;
// ... then see how adding an index affects the code
- lookup = new PropertyIndexLookup(
- new PropertyIndexHook(builder).processCommit(before, after));
+ IndexHook p = new PropertyIndexHook(builder);
+ after.compareAgainstBaseState(before, p.preProcess());
+ p.postProcess();
+ p.close();
+
+ lookup = new PropertyIndexLookup(builder.getNodeState());
long withIndex = System.nanoTime();
assertEquals(ImmutableSet.of("a", "b"), lookup.find("foo", "abc"));
assertEquals(ImmutableSet.of("b"), lookup.find("foo", "def"));
@@ -81,7 +86,9 @@ public class PropertyIndexTest {
// Add index definition
NodeBuilder builder = root.builder();
- builder.child("oak:index").child("fooIndex").setProperty("propertyNames", Arrays.asList("foo", "extrafoo"), Type.STRINGS);
+ builder.child("oak:index").child("fooIndex")
+ .setProperty("jcr:primaryType", "oak:queryIndexDefinition", Type.NAME)
+ .setProperty("propertyNames", Arrays.asList("foo", "extrafoo"), Type.STRINGS);
NodeState before = builder.getNodeState();
// Add some content and process it through the property index hook
@@ -106,8 +113,12 @@ public class PropertyIndexTest {
withoutIndex = System.nanoTime() - withoutIndex;
// ... then see how adding an index affects the code
- lookup = new PropertyIndexLookup(
- new PropertyIndexHook(builder).processCommit(before, after));
+ IndexHook p = new PropertyIndexHook(builder);
+ after.compareAgainstBaseState(before, p.preProcess());
+ p.postProcess();
+ p.close();
+
+ lookup = new PropertyIndexLookup(builder.getNodeState());
long withIndex = System.nanoTime();
assertEquals(ImmutableSet.of("a", "b"), lookup.find("foo", "abc"));
assertEquals(ImmutableSet.of("b"), lookup.find("foo", "def"));