Java tutorial
/* * JaLingo, http://jalingo.sourceforge.net/ * * Copyright (c) 2002-2006 Oleksandr Shyshko * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package ja.centre.util.io.nio; import ja.centre.util.assertions.Arguments; import ja.centre.util.assertions.States; import ja.centre.util.io.Files; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.io.Closeable; import java.io.IOException; import java.io.RandomAccessFile; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.security.AccessController; import java.security.PrivilegedAction; /** * Workaraund against J2SE BUG 4724038: "(fs) Add unmap method to MappedByteBuffer". * Method "clean" was taken from comments from post:<br> * <br> * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4724038 */ public class MappedByteBufferWrapper implements Closeable { private static final Log LOG = LogFactory.getLog(MappedByteBufferWrapper.class); private RandomAccessFile raf; private MappedByteBuffer buffer; private String fileName; public MappedByteBufferWrapper(String fileName) throws IOException { Arguments.assertNotNull("fileName", fileName); Files.assertExists(fileName); LOG.info("Opening \"" + fileName + "\"..."); this.fileName = fileName; try { raf = new RandomAccessFile(fileName, "rw"); try { initBuffer(); } catch (IOException e) { LOG.info("Could not lock file \"" + fileName + "\". Switching to non-locking mode..."); Files.closeQuietly(raf); raf = new RandomAccessFile(fileName, "r"); initBuffer(); } } catch (IOException e) { Files.closeQuietly(raf); throw e; } } private void initBuffer() throws IOException { buffer = raf.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, raf.getChannel().size()); } public MappedByteBuffer getMappedByteBuffer() { return buffer; } public void close() throws IOException { States.assertNotNull(buffer, "Expected to be not closed"); LOG.info("Closing \"" + fileName + "\"..."); clean(buffer); buffer = null; //lock.release(); raf.close(); raf = null; } private void clean(final MappedByteBuffer buffer) { AccessController.doPrivileged(new PrivilegedAction<Object>() { public Object run() { try { Method cleanerMethod = buffer.getClass().getMethod("cleaner"); cleanerMethod.setAccessible(true); sun.misc.Cleaner cleaner = (sun.misc.Cleaner) cleanerMethod.invoke(buffer); cleaner.clean(); } catch (IllegalAccessException e) { States.shouldNeverReachHere(e); } catch (NoSuchMethodException e) { States.shouldNeverReachHere(e); } catch (InvocationTargetException e) { States.shouldNeverReachHere(e); } return null; } }); } public String toString() { return "MappedByteBufferWrapper{" + "fileName='" + fileName + '\'' + '}'; } }