]> source.dussan.org Git - jackcess.git/commitdiff
better fix for switching read-only file formats to read-only mode, wrap with read...
authorJames Ahlborn <jtahlborn@yahoo.com>
Thu, 17 Nov 2016 02:32:32 +0000 (02:32 +0000)
committerJames Ahlborn <jtahlborn@yahoo.com>
Thu, 17 Nov 2016 02:32:32 +0000 (02:32 +0000)
git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@1057 f203690c-595d-4dc9-a70b-905162fa7fd2

src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java
src/main/java/com/healthmarketscience/jackcess/impl/UsageMap.java
src/main/java/com/healthmarketscience/jackcess/util/ReadOnlyFileChannel.java [new file with mode: 0644]

index ab01d0b519e0a4773d8e25698962804518311d9c..ac253fb41330984a681d34223726a07386fb1527 100644 (file)
@@ -69,6 +69,7 @@ import com.healthmarketscience.jackcess.util.CaseInsensitiveColumnMatcher;
 import com.healthmarketscience.jackcess.util.ColumnValidatorFactory;
 import com.healthmarketscience.jackcess.util.ErrorHandler;
 import com.healthmarketscience.jackcess.util.LinkResolver;
+import com.healthmarketscience.jackcess.util.ReadOnlyFileChannel;
 import com.healthmarketscience.jackcess.util.SimpleColumnValidatorFactory;
 import com.healthmarketscience.jackcess.util.TableIterableBuilder;
 import org.apache.commons.lang.builder.ToStringBuilder;
@@ -389,22 +390,14 @@ public class DatabaseImpl implements Database
         JetFormat jetFormat = JetFormat.getFormat(channel);
 
         if(jetFormat.READ_ONLY) {
-
-          if(closeChannel) {
-            // we own the channel, close and re-open read only
-            ByteUtil.closeQuietly(channel);
-            channel = null;
-            readOnly = true;
-            channel = openChannel(mdbFile, readOnly);
-          } else {
-            throw new IOException("file format " + 
-                                  jetFormat.getPossibleFileFormats().values() +
-                                  " does not support writing for " + mdbFile);
-          }
+          // wrap the channel with a read-only version to enforce
+          // non-writability
+          channel = new ReadOnlyFileChannel(channel);
+          readOnly = true;
         }
       }
 
-      DatabaseImpl db = new DatabaseImpl(mdbFile, channel, closeChannel, autoSync, 
+      DatabaseImpl db = new DatabaseImpl(mdbFile, channel, closeChannel, autoSync,
                                          null, charset, timeZone, provider);
       success = true;
       return db;
index 4a9eab029ddbc48d8f944705b64f4bcd8936b473..c67bcba583cd853e64718c4ab48168beb8bc6e7b 100644 (file)
@@ -477,8 +477,7 @@ public class UsageMap
   {
     private final int _maxInlinePages;
     
-    protected InlineHandler()
-      throws IOException
+    protected InlineHandler() throws IOException
     {
       _maxInlinePages = (getInlineDataEnd() - getInlineDataStart()) * 8;
       int startPage = getTableBuffer().getInt(getRowStart() + 1);
@@ -714,8 +713,7 @@ public class UsageMap
       TempPageHolder.newHolder(TempBufferHolder.Type.SOFT);
     private final int _maxPagesPerUsageMapPage;
   
-    private ReferenceHandler()
-      throws IOException
+    private ReferenceHandler() throws IOException
     {
       _maxPagesPerUsageMapPage = ((getFormat().PAGE_SIZE - 
                                    getFormat().OFFSET_USAGE_MAP_PAGE_DATA) * 8);
diff --git a/src/main/java/com/healthmarketscience/jackcess/util/ReadOnlyFileChannel.java b/src/main/java/com/healthmarketscience/jackcess/util/ReadOnlyFileChannel.java
new file mode 100644 (file)
index 0000000..85620e8
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+Copyright (c) 2016 James Ahlborn
+
+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.
+*/
+
+package com.healthmarketscience.jackcess.util;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
+import java.nio.channels.NonWritableChannelException;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.WritableByteChannel;
+import com.healthmarketscience.jackcess.Database;
+
+/**
+ * Wrapper for existing FileChannel which is read-only.
+ * <p/>
+ * Implementation note: this class is optimized for use with {@link Database}.
+ * Therefore not all methods may be implemented.
+ * 
+ * @author James Ahlborn
+ * @usage _advanced_class_
+ */
+public class ReadOnlyFileChannel extends FileChannel
+{
+  private final FileChannel _delegate;
+  
+  public ReadOnlyFileChannel(FileChannel delegate) {
+    _delegate = delegate;
+  }
+
+  @Override
+  public int read(ByteBuffer dst) throws IOException {
+    return _delegate.read(dst);
+  }
+
+  @Override
+  public long read(ByteBuffer[] dsts, int offset, int length) throws IOException {
+    return _delegate.read(dsts, offset, length);
+  }
+
+  @Override
+  public int read(ByteBuffer dst, long position) throws IOException {
+    return _delegate.read(dst, position);
+  }
+
+  @Override
+  public long position() throws IOException {
+    return _delegate.position();
+  }
+
+  @Override
+  public FileChannel position(long newPosition) throws IOException {
+    _delegate.position(newPosition);
+    return this;
+  }
+
+  @Override
+  public long size() throws IOException {
+    return _delegate.size();
+  }
+
+  @Override
+  public FileChannel truncate(long size) throws IOException {
+    throw new NonWritableChannelException();
+  }
+
+  @Override
+  public void force(boolean metaData) throws IOException {
+    // do nothing
+  }
+
+  @Override
+  public long transferTo(long position, long count, WritableByteChannel target) 
+    throws IOException 
+  {
+    return _delegate.transferTo(position, count, target);
+  }
+
+  @Override
+  public long transferFrom(ReadableByteChannel src, long position, long count) 
+    throws IOException 
+  {
+    throw new NonWritableChannelException();
+  }
+
+  @Override
+  public int write(ByteBuffer src, long position) throws IOException {
+    throw new NonWritableChannelException();
+  }
+
+
+  @Override
+  public int write(ByteBuffer src) throws IOException {
+    throw new NonWritableChannelException();
+  }
+
+  @Override
+  public long write(ByteBuffer[] srcs, int offset, int length) 
+    throws IOException 
+  {
+    throw new NonWritableChannelException();
+  }
+
+  @Override
+  public MappedByteBuffer map(MapMode mode, long position, long size) 
+    throws IOException 
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public FileLock lock(long position, long size, boolean shared) 
+    throws IOException 
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public FileLock tryLock(long position, long size, boolean shared) 
+    throws IOException 
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  protected void implCloseChannel() throws IOException {
+    _delegate.close();
+  }
+}