Index: solr/core/src/java/org/apache/solr/search/SolrIndexReader.java =================================================================== --- solr/core/src/java/org/apache/solr/search/SolrIndexReader.java (revision 1211309) +++ solr/core/src/java/org/apache/solr/search/SolrIndexReader.java (working copy) @@ -378,11 +378,6 @@ } @Override - public int getRefCount() { - return in.getRefCount(); - } - - @Override public IndexReader reopen(IndexCommit commit) throws CorruptIndexException, IOException { return in.reopen(commit); } @@ -426,66 +421,11 @@ } @Override - public void decRef() throws IOException { - in.decRef(); - } - - @Override - public void deleteDocument(int docNum) throws StaleReaderException, CorruptIndexException, LockObtainFailedException, IOException { - in.deleteDocument(docNum); - } - - @Override - public int deleteDocuments(Term term) throws StaleReaderException, CorruptIndexException, LockObtainFailedException, IOException { - return in.deleteDocuments(term); - } - - @Override - public Document document(int n) throws CorruptIndexException, IOException { - return in.document(n); - } - -// @Override -// public String getCommitUserData() { -// return in.getCommitUserData(); -// } - - @Override public IndexCommit getIndexCommit() throws IOException { return in.getIndexCommit(); } @Override - public void incRef() { - in.incRef(); - } - - @Override - public int numDeletedDocs() { - return in.numDeletedDocs(); - } - - @Override - public void setNorm(int doc, String field, byte value) throws StaleReaderException, CorruptIndexException, LockObtainFailedException, IOException { - in.setNorm(doc, field, value); - } - - @Override - public void setNorm(int doc, String field, float value) throws StaleReaderException, CorruptIndexException, LockObtainFailedException, IOException { - in.setNorm(doc, field, value); - } - - @Override - public TermPositions termPositions(Term term) throws IOException { - return in.termPositions(term); - } - - @Override - public void undeleteAll() throws StaleReaderException, CorruptIndexException, LockObtainFailedException, IOException { - in.undeleteAll(); - } - - @Override public Object getCoreCacheKey() { return in.getCoreCacheKey(); } Index: lucene/CHANGES.txt =================================================================== --- lucene/CHANGES.txt (revision 1211309) +++ lucene/CHANGES.txt (working copy) @@ -11,6 +11,13 @@ FieldCacheTermsFilter.FieldCacheTermsFilterDocIdSet was removed and replaced by another internal implementation. (Uwe Schindler) +* LUCENE-3620: FilterIndexReader now overrides all methods of IndexReader that + it should (note that some are still not overridden, as they should be + overridden by sub-classes only). In the process, some methods of IndexReader + were made final. This is not expected to affect many apps, since these methods + already delegate to abstract methods, which you had to already override + anyway. (Shai Erera) + Security fixes * LUCENE-3588: Try harder to prevent SIGSEGV on cloned MMapIndexInputs: Index: lucene/src/test/org/apache/lucene/index/TestFilterIndexReader.java =================================================================== --- lucene/src/test/org/apache/lucene/index/TestFilterIndexReader.java (revision 1211309) +++ lucene/src/test/org/apache/lucene/index/TestFilterIndexReader.java (working copy) @@ -18,17 +18,20 @@ */ -import org.apache.lucene.util.LuceneTestCase; +import java.io.IOException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.HashSet; + import junit.framework.TestSuite; import junit.textui.TestRunner; import org.apache.lucene.analysis.MockAnalyzer; -import org.apache.lucene.store.Directory; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; +import org.apache.lucene.store.Directory; +import org.apache.lucene.util.LuceneTestCase; -import java.io.IOException; - public class TestFilterIndexReader extends LuceneTestCase { private static class TestReader extends FilterIndexReader { @@ -136,4 +139,29 @@ reader.close(); directory.close(); } + + public void testOverrideMethods() throws Exception { + HashSet methodsThatShouldNotBeOverridden = new HashSet(); + methodsThatShouldNotBeOverridden.add("reopen"); + methodsThatShouldNotBeOverridden.add("doOpenIfChanged"); + methodsThatShouldNotBeOverridden.add("clone"); + boolean fail = false; + for (Method m : FilterIndexReader.class.getMethods()) { + int mods = m.getModifiers(); + if (Modifier.isStatic(mods) || Modifier.isFinal(mods)) { + continue; + } + Class< ? > declaringClass = m.getDeclaringClass(); + String name = m.getName(); + if (declaringClass != FilterIndexReader.class && declaringClass != Object.class && !methodsThatShouldNotBeOverridden.contains(name)) { + System.err.println("method is not overridden by FilterIndexReader: " + name); + fail = true; + } else if (declaringClass == FilterIndexReader.class && methodsThatShouldNotBeOverridden.contains(name)) { + System.err.println("method should not be overridden by FilterIndexReader: " + name); + fail = true; + } + } + assertFalse("FilterIndexReader overrides (or not) some problematic methods; see log above", fail); + } + } Index: lucene/src/java/org/apache/lucene/index/FilterIndexReader.java =================================================================== --- lucene/src/java/org/apache/lucene/index/FilterIndexReader.java (revision 1211309) +++ lucene/src/java/org/apache/lucene/index/FilterIndexReader.java (working copy) @@ -124,6 +124,18 @@ } @Override + public IndexCommit getIndexCommit() throws IOException { + ensureOpen(); + return in.getIndexCommit(); + } + + @Override + public int getTermInfosIndexDivisor() { + ensureOpen(); + return in.getTermInfosIndexDivisor(); + } + + @Override public TermFreqVector[] getTermFreqVectors(int docNumber) throws IOException { ensureOpen(); @@ -137,7 +149,6 @@ return in.getTermFreqVector(docNumber, field); } - @Override public void getTermFreqVector(int docNumber, String field, TermVectorMapper mapper) throws IOException { ensureOpen(); @@ -151,6 +162,12 @@ } @Override + public long getUniqueTermCount() throws IOException { + ensureOpen(); + return in.getUniqueTermCount(); + } + + @Override public int numDocs() { // Don't call ensureOpen() here (it could affect performance) return in.numDocs(); Index: lucene/src/java/org/apache/lucene/index/ParallelReader.java =================================================================== --- lucene/src/java/org/apache/lucene/index/ParallelReader.java (revision 1211309) +++ lucene/src/java/org/apache/lucene/index/ParallelReader.java (working copy) @@ -421,12 +421,6 @@ } @Override - public TermPositions termPositions(Term term) throws IOException { - ensureOpen(); - return new ParallelTermPositions(term); - } - - @Override public TermPositions termPositions() throws IOException { ensureOpen(); return new ParallelTermPositions(); Index: lucene/src/java/org/apache/lucene/index/IndexReader.java =================================================================== --- lucene/src/java/org/apache/lucene/index/IndexReader.java (revision 1211309) +++ lucene/src/java/org/apache/lucene/index/IndexReader.java (working copy) @@ -32,7 +32,6 @@ import org.apache.lucene.search.SearcherManager; // javadocs import org.apache.lucene.store.*; import org.apache.lucene.util.ArrayUtil; -import org.apache.lucene.util.ReaderUtil; // for javadocs import org.apache.lucene.util.VirtualMethod; /** IndexReader is an abstract class, providing an interface for accessing an @@ -177,7 +176,7 @@ static int DEFAULT_TERMS_INDEX_DIVISOR = 1; /** Expert: returns the current refCount for this reader */ - public int getRefCount() { + public final int getRefCount() { return refCount.get(); } @@ -196,7 +195,7 @@ * @see #decRef * @see #tryIncRef */ - public void incRef() { + public final void incRef() { ensureOpen(); refCount.incrementAndGet(); } @@ -224,7 +223,7 @@ * @see #decRef * @see #incRef */ - public boolean tryIncRef() { + public final boolean tryIncRef() { int count; while ((count = refCount.get()) > 0) { if (refCount.compareAndSet(count, count+1)) { @@ -265,7 +264,7 @@ * * @see #incRef */ - public void decRef() throws IOException { + public final void decRef() throws IOException { ensureOpen(); final int rc = refCount.getAndDecrement(); if (rc == 1) { @@ -1090,7 +1089,7 @@ public abstract int maxDoc(); /** Returns the number of deleted documents. */ - public int numDeletedDocs() { + public final int numDeletedDocs() { return maxDoc() - numDocs(); } @@ -1107,7 +1106,7 @@ * @throws CorruptIndexException if the index is corrupt * @throws IOException if there is a low-level IO error */ - public Document document(int n) throws CorruptIndexException, IOException { + public final Document document(int n) throws CorruptIndexException, IOException { ensureOpen(); if (n < 0 || n >= maxDoc()) { throw new IllegalArgumentException("docID must be >= 0 and < maxDoc=" + maxDoc() + " (got docID=" + n + ")"); @@ -1198,7 +1197,7 @@ * @throws IOException if there is a low-level IO error * @throws IllegalStateException if the field does not index norms */ - public synchronized void setNorm(int doc, String field, byte value) + public final synchronized void setNorm(int doc, String field, byte value) throws StaleReaderException, CorruptIndexException, LockObtainFailedException, IOException { ensureOpen(); acquireWriteLock(); @@ -1228,7 +1227,7 @@ * This method will be removed in Lucene 4.0 */ @Deprecated - public void setNorm(int doc, String field, float value) + public final void setNorm(int doc, String field, float value) throws StaleReaderException, CorruptIndexException, LockObtainFailedException, IOException { ensureOpen(); setNorm(doc, field, Similarity.getDefault().encodeNormValue(value)); @@ -1305,7 +1304,7 @@ * greater than all that precede it in the enumeration. * @throws IOException if there is a low-level IO error */ - public TermPositions termPositions(Term term) throws IOException { + public final TermPositions termPositions(Term term) throws IOException { ensureOpen(); TermPositions termPositions = termPositions(); termPositions.seek(term); @@ -1334,7 +1333,7 @@ * be obtained) * @throws IOException if there is a low-level IO error */ - public synchronized void deleteDocument(int docNum) throws StaleReaderException, CorruptIndexException, LockObtainFailedException, IOException { + public final synchronized void deleteDocument(int docNum) throws StaleReaderException, CorruptIndexException, LockObtainFailedException, IOException { ensureOpen(); acquireWriteLock(); hasChanges = true; @@ -1365,7 +1364,7 @@ * be obtained) * @throws IOException if there is a low-level IO error */ - public int deleteDocuments(Term term) throws StaleReaderException, CorruptIndexException, LockObtainFailedException, IOException { + public final int deleteDocuments(Term term) throws StaleReaderException, CorruptIndexException, LockObtainFailedException, IOException { ensureOpen(); TermDocs docs = termDocs(term); if (docs == null) return 0; @@ -1400,7 +1399,7 @@ * @throws CorruptIndexException if the index is corrupt * @throws IOException if there is a low-level IO error */ - public synchronized void undeleteAll() throws StaleReaderException, CorruptIndexException, LockObtainFailedException, IOException { + public final synchronized void undeleteAll() throws StaleReaderException, CorruptIndexException, LockObtainFailedException, IOException { ensureOpen(); acquireWriteLock(); hasChanges = true; Index: lucene/contrib/memory/src/java/org/apache/lucene/index/memory/MemoryIndex.java =================================================================== --- lucene/contrib/memory/src/java/org/apache/lucene/index/memory/MemoryIndex.java (revision 1211309) +++ lucene/contrib/memory/src/java/org/apache/lucene/index/memory/MemoryIndex.java (working copy) @@ -1148,12 +1148,6 @@ return 1; } - @Override - public Document document(int n) { - if (DEBUG) System.err.println("MemoryIndexReader.document"); - return new Document(); // there are no stored fields - } - //When we convert to JDK 1.5 make this Set @Override public Document document(int n, FieldSelector fieldSelector) throws IOException { Index: lucene/contrib/instantiated/src/java/org/apache/lucene/store/instantiated/InstantiatedIndexReader.java =================================================================== --- lucene/contrib/instantiated/src/java/org/apache/lucene/store/instantiated/InstantiatedIndexReader.java (revision 1211309) +++ lucene/contrib/instantiated/src/java/org/apache/lucene/store/instantiated/InstantiatedIndexReader.java (working copy) @@ -270,32 +270,6 @@ */ @Override public Document document(int n, FieldSelector fieldSelector) throws CorruptIndexException, IOException { - return document(n); - } - - /** - * Returns the stored fields of the nth - * Document in this index. - *

- * Warning! - * The resulting document is the actual stored document instance - * and not a deserialized clone as retuned by an IndexReader - * over a {@link org.apache.lucene.store.Directory}. - * I.e., if you need to touch the document, clone it first! - *

- * This can also be seen as a feature for live changes of stored values, - * but be careful! Adding a field with an name unknown to the index - * or to a field with previously no stored values will make - * {@link org.apache.lucene.store.instantiated.InstantiatedIndexReader#getFieldNames(org.apache.lucene.index.IndexReader.FieldOption)} - * out of sync, causing problems for instance when merging the - * instantiated index to another index. - * - * @throws CorruptIndexException if the index is corrupt - * @throws IOException if there is a low-level IO error - */ - - @Override - public Document document(int n) throws IOException { return isDeleted(n) ? null : getIndex().getDocumentsByNumber()[n].getDocument(); } Index: lucene/contrib/misc/src/java/org/apache/lucene/index/IndexSorter.java =================================================================== --- lucene/contrib/misc/src/java/org/apache/lucene/index/IndexSorter.java (revision 1211309) +++ lucene/contrib/misc/src/java/org/apache/lucene/index/IndexSorter.java (working copy) @@ -195,11 +195,6 @@ } @Override - public Document document(int n) throws IOException { - return document(n, null); - } - - @Override public Document document(int n, FieldSelector fieldSelector) throws CorruptIndexException, IOException { return super.document(newToOld[n], fieldSelector);