/* * Hibernate Search, full-text search for your domain model * * License: GNU Lesser General Public License (LGPL), version 2.1 or later * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. */ package org.hibernate.search.testsupport.readerprovider; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertEquals; import java.io.IOException; import java.util.Collections; import org.apache.lucene.document.DocumentStoredFieldVisitor; import org.apache.lucene.index.DirectoryReader; import org.apache.lucene.index.DocValuesType; import org.apache.lucene.index.FieldInfo; import org.apache.lucene.index.FilterDirectoryReader; import org.apache.lucene.index.FilterDirectoryReader.SubReaderWrapper; import org.apache.lucene.index.FilterLeafReader; import org.apache.lucene.index.IndexOptions; import org.apache.lucene.index.LeafReader; import org.apache.lucene.index.StoredFieldVisitor; import org.apache.lucene.index.StoredFieldVisitor.Status; import org.hibernate.search.exception.SearchException; import org.hibernate.search.indexes.impl.NotSharedReaderProvider; import org.hibernate.search.indexes.spi.ReaderProvider; import org.hibernate.search.query.engine.impl.ReusableDocumentStoredFieldVisitor; /** * {@code ReaderProvider} to inspect the type of {@code FieldSelector} being applied. * * @author Sanne Grinovero (C) 2011 Red Hat Inc. */ public final class FieldSelectorLeakingReaderProvider extends NotSharedReaderProvider implements ReaderProvider { private static volatile StoredFieldVisitor fieldSelector; public static void resetFieldSelector() { fieldSelector = null; } /** * Verifies the FieldSelector being used contains the listed field names (and no more). * Note that DocumentBuilder.CLASS_FIELDNAME is always used. * @param expectedFieldNames * @throws IOException */ public static void assertFieldSelectorEnabled(String... expectedFieldNames) throws IOException { if ( expectedFieldNames == null || expectedFieldNames.length == 0 ) { assertFieldSelectorDisabled(); } else { assertNotNull( FieldSelectorLeakingReaderProvider.fieldSelector ); assertTrue( fieldSelector instanceof ReusableDocumentStoredFieldVisitor ); ReusableDocumentStoredFieldVisitor visitor = (ReusableDocumentStoredFieldVisitor) fieldSelector; assertEquals( expectedFieldNames.length, visitor.countAcceptedFields() ); for ( String fieldName : expectedFieldNames ) { FieldInfo fieldId = forgeFieldInfo( fieldName ); assertEquals( Status.YES, visitor.needsField( fieldId ) ); } } } static FieldInfo forgeFieldInfo(String fieldName) { //Specific options besides the field name aren't important: //we just need to satisfy the constructor return new FieldInfo( fieldName, 0, false, true, false, IndexOptions.DOCS, DocValuesType.SORTED, 1l, Collections.<String,String>emptyMap() ); } public static void assertFieldSelectorDisabled() { StoredFieldVisitor fieldVisitor = FieldSelectorLeakingReaderProvider.fieldSelector; //DocumentStoredFieldVisitor is the type of the default fieldVisitor, so it's expected: assertTrue( fieldVisitor == null || fieldVisitor instanceof DocumentStoredFieldVisitor ); } @Override public DirectoryReader openIndexReader() { DirectoryReader originalReader = super.openIndexReader(); try { LeakingDirectoryReader wrappedReader = new LeakingDirectoryReader( originalReader ); return wrappedReader; } catch (IOException ioe) { throw new SearchException( ioe ); } } private final class LeakingDirectoryReader extends FilterDirectoryReader { public LeakingDirectoryReader(DirectoryReader in) throws IOException { super( in, new LeakingSubReaderWrapper() ); } @Override protected DirectoryReader doWrapDirectoryReader(DirectoryReader in) throws IOException { return new LeakingDirectoryReader( in ); } } private final class LeakingSubReaderWrapper extends SubReaderWrapper { @Override public LeafReader wrap(LeafReader reader) { return new LeakingAtomicReader( reader ); } } private final class LeakingAtomicReader extends FilterLeafReader { public LeakingAtomicReader(LeafReader in) { super( in ); } @Override public void document(int docID, StoredFieldVisitor visitor) throws IOException { super.document( docID, visitor ); FieldSelectorLeakingReaderProvider.fieldSelector = visitor; } } }