Index: oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/OakDirectory.java =================================================================== --- oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/OakDirectory.java (revision 1779196) +++ oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/OakDirectory.java (working copy) @@ -28,6 +28,8 @@ import java.util.List; import java.util.Set; +import javax.annotation.Nonnull; + import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; import com.google.common.io.ByteStreams; @@ -36,6 +38,8 @@ import org.apache.jackrabbit.oak.api.PropertyState; import org.apache.jackrabbit.oak.api.Type; import org.apache.jackrabbit.oak.commons.StringUtils; +import org.apache.jackrabbit.oak.plugins.blob.BlobStoreBlob; +import org.apache.jackrabbit.oak.spi.blob.BlobStore; import org.apache.jackrabbit.oak.spi.state.NodeBuilder; import org.apache.jackrabbit.oak.util.PerfLogger; import org.apache.lucene.store.AlreadyClosedException; @@ -83,6 +87,7 @@ private final Set fileNames = Sets.newConcurrentHashSet(); private final boolean activeDeleteEnabled; private final String indexName; + private final BlobFactory blobFactory; public OakDirectory(NodeBuilder builder, IndexDefinition definition, boolean readOnly) { this(builder, INDEX_DATA_CHILD_NAME, definition, readOnly); @@ -89,6 +94,11 @@ } public OakDirectory(NodeBuilder builder, String dataNodeName, IndexDefinition definition, boolean readOnly) { + this(builder, dataNodeName, definition, readOnly, new NodeBuilderBlobFactory(builder)); + } + + public OakDirectory(NodeBuilder builder, String dataNodeName, IndexDefinition definition, + boolean readOnly, BlobFactory blobFactory) { this.lockFactory = NoLockFactory.getNoLockFactory(); this.builder = builder; this.directoryBuilder = readOnly ? builder.getChildNode(dataNodeName) : builder.child(dataNodeName); @@ -97,6 +107,7 @@ this.fileNames.addAll(getListing()); this.activeDeleteEnabled = definition.getActiveDeleteEnabled(); this.indexName = definition.getIndexName(); + this.blobFactory = blobFactory; } @Override @@ -141,7 +152,7 @@ @Override public long fileLength(String name) throws IOException { NodeBuilder file = directoryBuilder.getChildNode(name); - OakIndexInput input = new OakIndexInput(name, file, indexName); + OakIndexInput input = new OakIndexInput(name, file, indexName, blobFactory); try { return input.length(); } finally { @@ -165,7 +176,7 @@ file = directoryBuilder.child(name); } fileNames.add(name); - return new OakIndexOutput(name, file, indexName); + return new OakIndexOutput(name, file, indexName, blobFactory); } @@ -174,7 +185,7 @@ throws IOException { NodeBuilder file = directoryBuilder.getChildNode(name); if (file.exists()) { - return new OakIndexInput(name, file, indexName); + return new OakIndexInput(name, file, indexName, blobFactory); } else { String msg = String.format("[%s] %s", indexName, name); throw new FileNotFoundException(msg); @@ -309,7 +320,10 @@ private final String dirDetails; - public OakIndexFile(String name, NodeBuilder file, String dirDetails) { + private final BlobFactory blobFactory; + + public OakIndexFile(String name, NodeBuilder file, String dirDetails, + @Nonnull BlobFactory blobFactory) { this.name = name; this.file = file; this.dirDetails = dirDetails; @@ -316,6 +330,7 @@ this.blobSize = determineBlobSize(file); this.uniqueKey = readUniqueKey(file); this.blob = new byte[blobSize]; + this.blobFactory = checkNotNull(blobFactory); PropertyState property = file.getProperty(JCR_DATA); if (property != null && property.getType() == BINARIES) { @@ -346,6 +361,7 @@ this.length = that.length; this.data = newArrayList(that.data); this.dataModified = that.dataModified; + this.blobFactory = that.blobFactory; } private void loadBlob(int i) throws IOException { @@ -373,7 +389,7 @@ in = new SequenceInputStream(in, new ByteArrayInputStream(uniqueKey)); } - Blob b = file.createBlob(in); + Blob b = blobFactory.createBlob(in); if (index < data.size()) { data.set(index, b); } else { @@ -501,10 +517,11 @@ private final WeakIdentityMap clones; private final String dirDetails; - public OakIndexInput(String name, NodeBuilder file, String dirDetails) { + public OakIndexInput(String name, NodeBuilder file, String dirDetails, + BlobFactory blobFactory) { super(name); this.dirDetails = dirDetails; - this.file = new OakIndexFile(name, file, dirDetails); + this.file = new OakIndexFile(name, file, dirDetails, blobFactory); clones = WeakIdentityMap.newConcurrentHashMap(); } @@ -584,9 +601,10 @@ private final String dirDetails; private final OakIndexFile file; - public OakIndexOutput(String name, NodeBuilder file, String dirDetails) throws IOException { + public OakIndexOutput(String name, NodeBuilder file, String dirDetails, + BlobFactory blobFactory) throws IOException { this.dirDetails = dirDetails; - this.file = new OakIndexFile(name, file, dirDetails); + this.file = new OakIndexFile(name, file, dirDetails, blobFactory); } @Override @@ -642,4 +660,36 @@ } + public interface BlobFactory { + + Blob createBlob(InputStream in) throws IOException; + } + + public static final class NodeBuilderBlobFactory implements BlobFactory { + + private final NodeBuilder builder; + + public NodeBuilderBlobFactory(NodeBuilder builder) { + this.builder = builder; + } + + @Override + public Blob createBlob(InputStream in) throws IOException { + return builder.createBlob(in); + } + } + + public static final class BlobStoreBlobFactory implements BlobFactory { + + private final BlobStore store; + + public BlobStoreBlobFactory(BlobStore store) { + this.store = store; + } + + @Override + public Blob createBlob(InputStream in) throws IOException { + return new BlobStoreBlob(store, store.writeBlob(in)); + } + } } Index: oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/OakDirectoryTest.java =================================================================== --- oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/OakDirectoryTest.java (revision 1779196) +++ oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/OakDirectoryTest.java (working copy) @@ -20,6 +20,7 @@ package org.apache.jackrabbit.oak.plugins.index.lucene; import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; @@ -27,6 +28,7 @@ import java.util.List; import java.util.Random; import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; import org.apache.commons.io.IOUtils; import org.apache.commons.io.input.NullInputStream; @@ -61,6 +63,7 @@ import static org.apache.jackrabbit.oak.api.Type.BINARIES; import static org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.INDEX_DATA_CHILD_NAME; import static org.apache.jackrabbit.oak.plugins.index.lucene.OakDirectory.PROP_BLOB_SIZE; +import static org.apache.jackrabbit.oak.plugins.index.lucene.OakDirectory.UNIQUE_KEY_SIZE; import static org.apache.jackrabbit.oak.plugins.nodetype.write.InitialContent.INITIAL_CONTENT; import static org.hamcrest.CoreMatchers.containsString; import static org.junit.Assert.assertEquals; @@ -168,7 +171,7 @@ assertEquals(blobSize, testNode.getProperty(PROP_BLOB_SIZE).getValue(Type.LONG).longValue()); List blobs = newArrayList(testNode.getProperty(JCR_DATA).getValue(BINARIES)); - assertEquals(blobSize + OakDirectory.UNIQUE_KEY_SIZE, blobs.get(0).length()); + assertEquals(blobSize + UNIQUE_KEY_SIZE, blobs.get(0).length()); return data; } @@ -419,6 +422,29 @@ assertEquals(0, dir.listAll().length); } + @Test + public void blobFactory() throws Exception { + final AtomicInteger numBlobs = new AtomicInteger(); + final int fileSize = 1024; + IndexDefinition def = new IndexDefinition(root, builder.getNodeState()); + OakDirectory.BlobFactory factory = new OakDirectory.BlobFactory() { + @Override + public Blob createBlob(InputStream in) throws IOException { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + IOUtils.copy(in, out); + byte[] data = out.toByteArray(); + assertEquals(fileSize + UNIQUE_KEY_SIZE, data.length); + numBlobs.incrementAndGet(); + return new ArrayBasedBlob(data); + } + }; + OakDirectory dir = new OakDirectory(builder, INDEX_DATA_CHILD_NAME, def, false, factory); + numBlobs.set(0); + writeFile(dir, "file", fileSize); + assertEquals(1, numBlobs.get()); + dir.close(); + } + private static void readInputToEnd(long expectedSize, IndexInput input) throws IOException { int COPY_BUFFER_SIZE = 16384; byte[] copyBuffer = new byte[(int) ONE_MB]; Index: . =================================================================== --- . (revision 1779196) +++ . (working copy) Property changes on: . ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /jackrabbit/oak/trunk:r1774141