package org.apache.lucene.limit; /** * Copyright 2005 The Apache Software Foundation * * Licensed 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. */ import java.io.File; import java.io.IOException; import java.util.Collection; import org.apache.lucene.document.Document; import org.apache.lucene.document.FieldSelector; 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.store.Directory; /** * Wraps a normal IndexReader to limit the amount of work performed by a * query. "Work" is defined as the number of docs and positions read. * Limiting work in this way helps protect against malicious queries. * * @author Martin Haye */ public class LimIndexReader extends IndexReader { private IndexReader wrapped; private int workLimit; private int workCount = 0; /** * Wrap an index reader and enforce the specified limit. * * @param toWrap The reader to wrap * @param workLimit Limit on the amount of wokr */ public LimIndexReader(IndexReader toWrap, int workLimit) { super(null); this.wrapped = toWrap; this.workLimit = workLimit; } /** * Called by LimTermDocs and LimTermPositions to notify us that a certain * amount of work has been done. We check the limit, and if exceeded, throw * an exception. * * @param amount How much work has been done. The unit is typically one * term or term-position. */ protected void work(int amount) throws IOException { workCount += amount; if (workCount > workLimit) throw new ExcessiveWorkException(); } // work() /*-----------------------------------------------------------------------* * METHODS THAT DO "WORK" *-----------------------------------------------------------------------*/ public Document document(int n, FieldSelector fieldSelector) throws IOException { Document ret = wrapped.document(n, fieldSelector); work(ret.getFields().size()); return ret; } /*-----------------------------------------------------------------------* * DELEGATED METHODS *-----------------------------------------------------------------------*/ public static long getCurrentVersion(File directory) throws IOException { return IndexReader.getCurrentVersion(directory); } public static long getCurrentVersion(String directory) throws IOException { return IndexReader.getCurrentVersion(directory); } public static long getCurrentVersion(Directory directory) throws IOException { return IndexReader.getCurrentVersion(directory); } public static boolean indexExists(File directory) { return IndexReader.indexExists(directory); } public static boolean indexExists(String directory) { return IndexReader.indexExists(directory); } public static boolean indexExists(Directory directory) throws IOException { return IndexReader.indexExists(directory); } public static boolean isLocked(String directory) throws IOException { return IndexReader.isLocked(directory); } public static boolean isLocked(Directory directory) throws IOException { return IndexReader.isLocked(directory); } public static IndexReader open(File path) throws IOException { assert false : "Method should never be called"; throw new RuntimeException(); } public static IndexReader open(String path) throws IOException { assert false : "Method should never be called"; throw new RuntimeException(); } public static IndexReader open(Directory directory) throws IOException { assert false : "Method should never be called"; throw new RuntimeException(); } public static void unlock(Directory directory) throws IOException { IndexReader.unlock(directory); } public Directory directory() { return wrapped.directory(); } public int docFreq(Term t) throws IOException { return wrapped.docFreq(t); } public Document document(int n) throws IOException { return wrapped.document(n); } public boolean equals(Object obj) { return wrapped.equals(obj); } public TermFreqVector getTermFreqVector(int docNumber, String field) throws IOException { return wrapped.getTermFreqVector(docNumber, field); } public TermFreqVector[] getTermFreqVectors(int docNumber) throws IOException { return wrapped.getTermFreqVectors(docNumber); } public boolean hasDeletions() { return wrapped.hasDeletions(); } public int hashCode() { return wrapped.hashCode(); } public boolean isDeleted(int n) { return wrapped.isDeleted(n); } public int maxDoc() { return wrapped.maxDoc(); } public byte[] norms(String field) throws IOException { return wrapped.norms(field); } public void norms(String field, byte[] bytes, int offset) throws IOException { wrapped.norms(field, bytes, offset); } public int numDocs() { return wrapped.numDocs(); } public void setNorm(int doc, String field, float value) throws IOException { wrapped.setNorm(doc, field, value); } public TermDocs termDocs() throws IOException { return new LimTermDocs(this, wrapped.termDocs()); } public TermDocs termDocs(Term term) throws IOException { return new LimTermDocs(this, wrapped.termDocs(term)); } public TermPositions termPositions() throws IOException { return new LimTermPositions(this, wrapped.termPositions()); } public TermPositions termPositions(Term term) throws IOException { return new LimTermPositions(this, wrapped.termPositions(term)); } public TermEnum terms() throws IOException { return wrapped.terms(); } public TermEnum terms(Term t) throws IOException { return wrapped.terms(t); } public String toString() { return wrapped.toString(); } protected void doClose() throws IOException { assert false : "method should never be called"; } protected void doCommit() throws IOException { assert false : "method should never be called"; } protected void doDelete(int docNum) throws IOException { assert false : "method should never be called"; } protected void doSetNorm(int doc, String field, byte value) throws IOException { assert false : "method should never be called"; } protected void doUndeleteAll() throws IOException { assert false : "method should never be called"; } public Collection getFieldNames(FieldOption opt) { return wrapped.getFieldNames(opt); } public long getVersion() { return wrapped.getVersion(); } public boolean hasNorms(String field) throws IOException { return wrapped.hasNorms(field); } public boolean isCurrent() throws IOException { return wrapped.isCurrent(); } public boolean isOptimized() { return wrapped.isOptimized(); } } // class LimIndexReader