/* * JBoss, Home of Professional Open Source * Copyright 2011 Red Hat Inc. and/or its affiliates and other contributors * as indicated by the @authors tag. All rights reserved. * See the copyright.txt in the distribution for a * full listing of individual contributors. * * This copyrighted material is made available to anyone wishing to use, * modify, copy, or redistribute it subject to the terms and conditions * of the GNU Lesser General Public License, v. 2.1. * This program is distributed in the hope that it will be useful, but WITHOUT A * 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, * v.2.1 along with this distribution; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301, USA. */ package org.hibernate.search.test.util; import java.io.IOException; import java.lang.reflect.Field; import java.util.Map; import org.apache.lucene.document.Document; import org.apache.lucene.document.FieldSelector; import org.apache.lucene.document.FieldSelectorResult; import org.apache.lucene.document.MapFieldSelector; import org.apache.lucene.index.CorruptIndexException; import org.apache.lucene.index.FieldInfos; import org.apache.lucene.index.IndexCommit; import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.Term; import org.apache.lucene.index.TermDocs; import org.apache.lucene.index.TermEnum; import org.apache.lucene.index.TermFreqVector; import org.apache.lucene.index.TermPositions; import org.apache.lucene.index.TermVectorMapper; import org.apache.lucene.store.Directory; import org.hibernate.search.SearchException; import org.hibernate.search.indexes.impl.NotSharedReaderProvider; import org.hibernate.search.indexes.spi.ReaderProvider; import org.hibernate.search.util.impl.ReflectionHelper; import static junit.framework.Assert.*; /** * ReaderProvider to inspect the type of FieldSelector being applied. * * @author Sanne Grinovero <sanne@hibernate.org> (C) 2011 Red Hat Inc. */ public class FieldSelectorLeakingReaderProvider extends NotSharedReaderProvider implements ReaderProvider { private static volatile FieldSelector fieldSelector; public static void resetFieldSelector() { fieldSelector = null; } /** * Verifies the FieldSelector being used contains the listed fieldnames (and no more). * Note that DocumentBuilder.CLASS_FIELDNAME is always used. * @param expectedFieldNames */ public static void assertFieldSelectorEnabled(String... expectedFieldNames) { if ( expectedFieldNames == null || expectedFieldNames.length == 0 ) { assertNull( FieldSelectorLeakingReaderProvider.fieldSelector ); } else { assertNotNull( FieldSelectorLeakingReaderProvider.fieldSelector ); MapFieldSelector selector = (MapFieldSelector) fieldSelector; Map<String, FieldSelectorResult> fieldSelections; try { Field field = MapFieldSelector.class.getDeclaredField( "fieldSelections" ); ReflectionHelper.setAccessible( field ); fieldSelections = (Map<String, FieldSelectorResult>) field.get( selector ); } catch (NoSuchFieldException e) { throw new SearchException( "Incompatible version of Lucene: MapFieldSelector.fieldSelections not available", e ); } catch (IllegalArgumentException e) { throw new SearchException( "Incompatible version of Lucene: MapFieldSelector.fieldSelections not available", e ); } catch (IllegalAccessException e) { throw new SearchException( "Incompatible version of Lucene: MapFieldSelector.fieldSelections not available", e ); } assertNotNull( fieldSelections ); assertEquals( expectedFieldNames.length, fieldSelections.size() ); } } public static void assertFieldSelectorDisabled() { assertNull( FieldSelectorLeakingReaderProvider.fieldSelector ); } @Override public IndexReader openIndexReader() { IndexReader indexReader = super.openIndexReader(); IndexReader leakingReader = new LeakingIndexReader( indexReader ); return leakingReader; } /** * Delegates are created via IDE code generation with some changes: * - the method {@link #document(int, FieldSelector)} * - method {@link #document(int)} * - the last ones: can't delegate as the method is not visible */ private static class LeakingIndexReader extends IndexReader { private final IndexReader delegate; LeakingIndexReader(IndexReader wrapped) { this.delegate = wrapped; } public int hashCode() { return delegate.hashCode(); } public boolean equals(Object obj) { return delegate.equals( obj ); } public String toString() { return delegate.toString(); } public Object clone() { return delegate.clone(); } public IndexReader clone(boolean openReadOnly) throws CorruptIndexException, IOException { return delegate.clone( openReadOnly ); } public Directory directory() { return delegate.directory(); } public long getVersion() { return delegate.getVersion(); } public Map<String, String> getCommitUserData() { return delegate.getCommitUserData(); } public boolean isCurrent() throws CorruptIndexException, IOException { return delegate.isCurrent(); } public TermFreqVector[] getTermFreqVectors(int docNumber) throws IOException { return delegate.getTermFreqVectors( docNumber ); } public TermFreqVector getTermFreqVector(int docNumber, String field) throws IOException { return delegate.getTermFreqVector( docNumber, field ); } public void getTermFreqVector(int docNumber, String field, TermVectorMapper mapper) throws IOException { delegate.getTermFreqVector( docNumber, field, mapper ); } public void getTermFreqVector(int docNumber, TermVectorMapper mapper) throws IOException { delegate.getTermFreqVector( docNumber, mapper ); } public int numDocs() { return delegate.numDocs(); } public int maxDoc() { return delegate.maxDoc(); } public Document document(int n, FieldSelector fieldSelector) throws CorruptIndexException, IOException { FieldSelectorLeakingReaderProvider.fieldSelector = fieldSelector; return delegate.document( n, fieldSelector ); } public boolean isDeleted(int n) { return delegate.isDeleted( n ); } public boolean hasDeletions() { return delegate.hasDeletions(); } public boolean hasNorms(String field) throws IOException { return delegate.hasNorms( field ); } public byte[] norms(String field) throws IOException { return delegate.norms( field ); } public void norms(String field, byte[] bytes, int offset) throws IOException { delegate.norms( field, bytes, offset ); } public TermEnum terms() throws IOException { return delegate.terms(); } public TermEnum terms(Term t) throws IOException { return delegate.terms( t ); } public int docFreq(Term t) throws IOException { return delegate.docFreq( t ); } public TermDocs termDocs(Term term) throws IOException { return delegate.termDocs( term ); } public TermDocs termDocs() throws IOException { return delegate.termDocs(); } public TermPositions termPositions() throws IOException { return delegate.termPositions(); } public IndexCommit getIndexCommit() throws IOException { return delegate.getIndexCommit(); } public IndexReader[] getSequentialSubReaders() { return delegate.getSequentialSubReaders(); } public Object getCoreCacheKey() { return delegate.getCoreCacheKey(); } public Object getDeletesCacheKey() { return delegate.getDeletesCacheKey(); } public long getUniqueTermCount() throws IOException { return delegate.getUniqueTermCount(); } public int getTermInfosIndexDivisor() { return delegate.getTermInfosIndexDivisor(); } protected void doSetNorm(int doc, String field, byte value) throws CorruptIndexException, IOException { throw new UnsupportedOperationException("delegate method is not visible - hope we don't need it"); } protected void doDelete(int docNum) throws CorruptIndexException, IOException { throw new UnsupportedOperationException("delegate method is not visible - hope we don't need it"); } protected void doUndeleteAll() throws CorruptIndexException, IOException { throw new UnsupportedOperationException("delegate method is not visible - hope we don't need it"); } protected void doCommit(Map<String, String> commitUserData) throws IOException { //can't implement as method is not visibile //not important either as method is deprecated and all Readers are read-only: nothing to commit //also, method is going to be removed. } protected void doClose() throws IOException { //can't implement as method is not visibile //not important either as method is deprecated and all Readers are read-only: nothing to flush on close //also, method is going to be removed. } @Override public FieldInfos getFieldInfos() { return delegate.getFieldInfos(); } } }