/* * Hibernate, Relational Persistence for Idiomatic Java * * JBoss, Home of Professional Open Source * Copyright 2012 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.leakdetection; import java.io.IOException; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import org.apache.lucene.store.DataInput; import org.apache.lucene.store.IndexInput; import org.apache.lucene.store.IndexOutput; import org.apache.lucene.store.RAMDirectory; /** * This Directory keeps track of opened IndexInput and IndexOutput * instances, making it possible to verify if any file was left open. * * @author Sanne Grinovero <sanne@hibernate.org> (C) 2012 Red Hat Inc. */ public class FileMonitoringDirectory extends RAMDirectory { private final ConcurrentMap<IndexOutput,IndexOutput> openOutputs = new ConcurrentHashMap<IndexOutput, IndexOutput>( 10 ); private final ConcurrentMap<IndexInput,IndexInput> openInputs = new ConcurrentHashMap<IndexInput, IndexInput>( 40 ); @Override public IndexOutput createOutput(String name) throws IOException { IndexOutput indexOutput = super.createOutput( name ); IndexOutputDelegate tracked = new IndexOutputDelegate( indexOutput ); openOutputs.put( tracked, tracked ); return tracked; } @Override public IndexInput openInput(String name) throws IOException { IndexInput openInput = super.openInput( name ); IndexInputDelegate tracked = new IndexInputDelegate( openInput ); openInputs.put( tracked, tracked ); return tracked; } /** * @return true if this Directory was closed */ public boolean isClosed() { return isOpen == false; } /** * @return true if all files opened by this Directory were also closed */ public boolean allFilesWereClosed() { return openInputs.isEmpty() && openOutputs.isEmpty(); } private class IndexOutputDelegate extends IndexOutput { private final IndexOutput delegate; public IndexOutputDelegate(IndexOutput delegate) { this.delegate = delegate; } public String toString() { return "IndexOutputDelegate to " + delegate.toString(); } public void close() throws IOException { delegate.close(); openOutputs.remove( IndexOutputDelegate.this ); } // All remaining methods are generated as plain delegators, // except equals & hashcode : public void writeByte(byte b) throws IOException { delegate.writeByte( b ); } public void flush() throws IOException { delegate.flush(); } public void writeBytes(byte[] b, int length) throws IOException { delegate.writeBytes( b, length ); } public long getFilePointer() { return delegate.getFilePointer(); } public void writeBytes(byte[] b, int offset, int length) throws IOException { delegate.writeBytes( b, offset, length ); } public void seek(long pos) throws IOException { delegate.seek( pos ); } public long length() throws IOException { return delegate.length(); } public void setLength(long length) throws IOException { delegate.setLength( length ); } public void writeInt(int i) throws IOException { delegate.writeInt( i ); } public void writeShort(short i) throws IOException { delegate.writeShort( i ); } public void writeLong(long i) throws IOException { delegate.writeLong( i ); } public void writeString(String s) throws IOException { delegate.writeString( s ); } public void copyBytes(DataInput input, long numBytes) throws IOException { delegate.copyBytes( input, numBytes ); } public void writeChars(String s, int start, int length) throws IOException { delegate.writeChars( s, start, length ); } public void writeChars(char[] s, int start, int length) throws IOException { delegate.writeChars( s, start, length ); } public void writeStringStringMap(Map<String, String> map) throws IOException { delegate.writeStringStringMap( map ); } } private class IndexInputDelegate extends IndexInput { private final IndexInput delegate; public IndexInputDelegate(IndexInput delegate) { super( delegate.toString() ); this.delegate = delegate; } public void close() throws IOException { delegate.close(); openInputs.remove( IndexInputDelegate.this ); } public String toString() { return "IndexInputDelegate to " + delegate.toString(); } // All remaining methods are generated as plain delegators, // except equals & hashcode : public void skipChars(int length) throws IOException { delegate.skipChars( length ); } public void setModifiedUTF8StringsMode() { delegate.setModifiedUTF8StringsMode(); } public byte readByte() throws IOException { return delegate.readByte(); } public void readBytes(byte[] b, int offset, int len) throws IOException { delegate.readBytes( b, offset, len ); } public void readBytes(byte[] b, int offset, int len, boolean useBuffer) throws IOException { delegate.readBytes( b, offset, len, useBuffer ); } public short readShort() throws IOException { return delegate.readShort(); } public long getFilePointer() { return delegate.getFilePointer(); } public void seek(long pos) throws IOException { delegate.seek( pos ); } public int readInt() throws IOException { return delegate.readInt(); } public long length() { return delegate.length(); } public void copyBytes(IndexOutput out, long numBytes) throws IOException { delegate.copyBytes( out, numBytes ); } public int readVInt() throws IOException { return delegate.readVInt(); } public long readLong() throws IOException { return delegate.readLong(); } public long readVLong() throws IOException { return delegate.readVLong(); } public String readString() throws IOException { return delegate.readString(); } public void readChars(char[] buffer, int start, int length) throws IOException { delegate.readChars( buffer, start, length ); } public Map<String, String> readStringStringMap() throws IOException { return delegate.readStringStringMap(); } } }