From 6626d6b28f21d550e5bde637ed3b9cea1806ab40 Mon Sep 17 00:00:00 2001 From: James Ahlborn Date: Thu, 29 Nov 2018 03:44:56 +0000 Subject: [PATCH] add support for Path git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/branches/jdk8@1233 f203690c-595d-4dc9-a70b-905162fa7fd2 --- .../jackcess/Database.java | 8 +- .../jackcess/DatabaseBuilder.java | 49 +++++++--- .../jackcess/impl/DatabaseImpl.java | 39 +++++--- .../jackcess/util/CustomLinkResolver.java | 66 ++++++++------ .../jackcess/util/MemFileChannel.java | 91 ++++++++++++++----- .../jackcess/DatabaseTest.java | 59 ++++++------ .../jackcess/TestUtil.java | 2 +- .../jackcess/impl/JetFormatTest.java | 33 +++---- .../jackcess/util/CustomLinkResolverTest.java | 12 +-- 9 files changed, 223 insertions(+), 136 deletions(-) diff --git a/src/main/java/com/healthmarketscience/jackcess/Database.java b/src/main/java/com/healthmarketscience/jackcess/Database.java index 2006dcf..6a7bcc4 100644 --- a/src/main/java/com/healthmarketscience/jackcess/Database.java +++ b/src/main/java/com/healthmarketscience/jackcess/Database.java @@ -21,6 +21,7 @@ import java.io.File; import java.io.Flushable; import java.io.IOException; import java.nio.charset.Charset; +import java.nio.file.Path; import java.util.ConcurrentModificationException; import java.util.Iterator; import java.util.List; @@ -29,8 +30,8 @@ import java.util.Set; import java.util.TimeZone; import com.healthmarketscience.jackcess.expr.EvalConfig; -import com.healthmarketscience.jackcess.query.Query; import com.healthmarketscience.jackcess.impl.DatabaseImpl; +import com.healthmarketscience.jackcess.query.Query; import com.healthmarketscience.jackcess.util.ColumnValidatorFactory; import com.healthmarketscience.jackcess.util.ErrorHandler; import com.healthmarketscience.jackcess.util.LinkResolver; @@ -178,6 +179,11 @@ public interface Database extends Iterable, Closeable, Flushable */ public File getFile(); + /** + * Returns the File underlying this Database + */ + public Path getPath(); + /** * @return The names of all of the user tables * @usage _general_method_ diff --git a/src/main/java/com/healthmarketscience/jackcess/DatabaseBuilder.java b/src/main/java/com/healthmarketscience/jackcess/DatabaseBuilder.java index 5aebdd4..dce1901 100644 --- a/src/main/java/com/healthmarketscience/jackcess/DatabaseBuilder.java +++ b/src/main/java/com/healthmarketscience/jackcess/DatabaseBuilder.java @@ -20,6 +20,7 @@ import java.io.File; import java.io.IOException; import java.nio.channels.FileChannel; import java.nio.charset.Charset; +import java.nio.file.Path; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; @@ -51,10 +52,10 @@ import com.healthmarketscience.jackcess.util.MemFileChannel; * @author James Ahlborn * @usage _general_class_ */ -public class DatabaseBuilder +public class DatabaseBuilder { /** the file name of the mdb to open/create */ - private File _mdbFile; + private Path _mdbFile; /** whether or not to open existing mdb read-only */ private boolean _readOnly; /** whether or not to auto-sync writes to the filesystem */ @@ -77,12 +78,16 @@ public class DatabaseBuilder /** database user-defined (if any) */ private Map _userProps; - + public DatabaseBuilder() { - this(null); + this((Path)null); } public DatabaseBuilder(File mdbFile) { + this(toPath(mdbFile)); + } + + public DatabaseBuilder(Path mdbFile) { _mdbFile = mdbFile; } @@ -93,6 +98,16 @@ public class DatabaseBuilder * @usage _general_method_ */ public DatabaseBuilder setFile(File mdbFile) { + return setPath(toPath(mdbFile)); + } + + /** + * File containing an existing database for {@link #open} or target file for + * new database for {@link #create} (in which case, tf this file already + * exists, it will be overwritten.) + * @usage _general_method_ + */ + public DatabaseBuilder setPath(Path mdbFile) { _mdbFile = mdbFile; return this; } @@ -183,7 +198,7 @@ public class DatabaseBuilder public DatabaseBuilder putDatabaseProperty(String name, Object value) { return putDatabaseProperty(name, null, value); } - + /** * Sets the database property with the given name and type to the given * value. @@ -193,7 +208,7 @@ public class DatabaseBuilder _dbProps = putProperty(_dbProps, name, type, value); return this; } - + /** * Sets the summary database property with the given name to the given * value. Attempts to determine the type of the property (see @@ -203,7 +218,7 @@ public class DatabaseBuilder public DatabaseBuilder putSummaryProperty(String name, Object value) { return putSummaryProperty(name, null, value); } - + /** * Sets the summary database property with the given name and type to * the given value. @@ -223,7 +238,7 @@ public class DatabaseBuilder public DatabaseBuilder putUserDefinedProperty(String name, Object value) { return putUserDefinedProperty(name, null, value); } - + /** * Sets the user-defined database property with the given name and type to * the given value. @@ -257,7 +272,7 @@ public class DatabaseBuilder * Creates a new Database using the configured information. */ public Database create() throws IOException { - Database db = DatabaseImpl.create(_fileFormat, _mdbFile, _channel, _autoSync, + Database db = DatabaseImpl.create(_fileFormat, _mdbFile, _channel, _autoSync, _charset, _timeZone); if(_dbProps != null) { PropertyMap props = db.getDatabaseProperties(); @@ -281,19 +296,19 @@ public class DatabaseBuilder * Open an existing Database. If the existing file is not writeable, the * file will be opened read-only. Auto-syncing is enabled for the returned * Database. - * + * * @param mdbFile File containing the database - * + * * @see DatabaseBuilder for more flexible Database opening * @usage _general_method_ */ public static Database open(File mdbFile) throws IOException { return new DatabaseBuilder(mdbFile).open(); } - + /** * Create a new Database for the given fileFormat - * + * * @param fileFormat version of new database. * @param mdbFile Location to write the new database to. If this file * already exists, it will be overwritten. @@ -301,8 +316,8 @@ public class DatabaseBuilder * @see DatabaseBuilder for more flexible Database creation * @usage _general_method_ */ - public static Database create(Database.FileFormat fileFormat, File mdbFile) - throws IOException + public static Database create(Database.FileFormat fileFormat, File mdbFile) + throws IOException { return new DatabaseBuilder(mdbFile).setFileFormat(fileFormat).create(); } @@ -330,4 +345,8 @@ public class DatabaseBuilder } return cal; } + + private static Path toPath(File file) { + return ((file != null) ? file.toPath() : null); + } } diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java b/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java index 220d5b0..03e32c8 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java @@ -20,7 +20,6 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; -import java.io.RandomAccessFile; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; import java.nio.ByteBuffer; @@ -28,6 +27,10 @@ import java.nio.channels.Channels; import java.nio.channels.FileChannel; import java.nio.channels.ReadableByteChannel; import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.OpenOption; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; @@ -198,9 +201,11 @@ public class DatabaseImpl implements Database SYSTEM_OBJECT_FLAG | ALT_SYSTEM_OBJECT_FLAG; /** read-only channel access mode */ - public static final String RO_CHANNEL_MODE = "r"; + public static final OpenOption[] RO_CHANNEL_OPTS = + {StandardOpenOption.READ}; /** read/write channel access mode */ - public static final String RW_CHANNEL_MODE = "rw"; + public static final OpenOption[] RW_CHANNEL_OPTS = + {StandardOpenOption.READ, StandardOpenOption.WRITE}; /** Name of the system object that is the parent of all tables */ private static final String SYSTEM_OBJECT_NAME_TABLES = "Tables"; @@ -252,7 +257,7 @@ public class DatabaseImpl implements Database Pattern.compile("[\\p{Cntrl}.!`\\]\\[]"); /** the File of the database */ - private final File _file; + private final Path _file; /** the simple name of the database */ private final String _name; /** Buffer to hold database pages */ @@ -362,20 +367,20 @@ public class DatabaseImpl implements Database * @usage _advanced_method_ */ public static DatabaseImpl open( - File mdbFile, boolean readOnly, FileChannel channel, + Path mdbFile, boolean readOnly, FileChannel channel, boolean autoSync, Charset charset, TimeZone timeZone, CodecProvider provider) throws IOException { boolean closeChannel = false; if(channel == null) { - if(!mdbFile.exists() || !mdbFile.canRead()) { + if(!Files.isReadable(mdbFile)) { throw new FileNotFoundException("given file does not exist: " + mdbFile); } // force read-only for non-writable files - readOnly |= !mdbFile.canWrite(); + readOnly |= !Files.isWritable(mdbFile); // open file channel channel = openChannel(mdbFile, readOnly); @@ -431,7 +436,7 @@ public class DatabaseImpl implements Database * @param timeZone TimeZone to use, if {@code null}, uses default * @usage _advanced_method_ */ - public static DatabaseImpl create(FileFormat fileFormat, File mdbFile, + public static DatabaseImpl create(FileFormat fileFormat, Path mdbFile, FileChannel channel, boolean autoSync, Charset charset, TimeZone timeZone) throws IOException @@ -482,11 +487,11 @@ public class DatabaseImpl implements Database * that name cannot be created, or if some other error occurs * while opening or creating the file */ - static FileChannel openChannel(final File mdbFile, final boolean readOnly) - throws FileNotFoundException + static FileChannel openChannel(Path mdbFile, boolean readOnly) + throws IOException { - final String mode = (readOnly ? RO_CHANNEL_MODE : RW_CHANNEL_MODE); - return new RandomAccessFile(mdbFile, mode).getChannel(); + OpenOption[] opts = (readOnly ? RO_CHANNEL_OPTS : RW_CHANNEL_OPTS); + return FileChannel.open(mdbFile, opts); } /** @@ -508,7 +513,7 @@ public class DatabaseImpl implements Database * @param charset Charset to use, if {@code null}, uses default * @param timeZone TimeZone to use, if {@code null}, uses default */ - protected DatabaseImpl(File file, FileChannel channel, boolean closeChannel, + protected DatabaseImpl(Path file, FileChannel channel, boolean closeChannel, boolean autoSync, FileFormat fileFormat, Charset charset, TimeZone timeZone, CodecProvider provider) throws IOException @@ -536,6 +541,10 @@ public class DatabaseImpl implements Database } public File getFile() { + return ((_file != null) ? _file.toFile() : null); + } + + public Path getPath() { return _file; } @@ -2096,11 +2105,11 @@ public class DatabaseImpl implements Database FILE_FORMAT_DETAILS.put(fileFormat, new FileFormatDetails(emptyFile, format)); } - private static String getName(File file) { + private static String getName(Path file) { if(file == null) { return ""; } - return file.getName(); + return file.getFileName().toString(); } private String withErrorContext(String msg) { diff --git a/src/main/java/com/healthmarketscience/jackcess/util/CustomLinkResolver.java b/src/main/java/com/healthmarketscience/jackcess/util/CustomLinkResolver.java index 7992d71..0463b2d 100644 --- a/src/main/java/com/healthmarketscience/jackcess/util/CustomLinkResolver.java +++ b/src/main/java/com/healthmarketscience/jackcess/util/CustomLinkResolver.java @@ -17,10 +17,11 @@ limitations under the License. package com.healthmarketscience.jackcess.util; import java.io.Closeable; -import java.io.File; import java.io.IOException; -import java.io.RandomAccessFile; import java.nio.channels.FileChannel; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Random; import com.healthmarketscience.jackcess.Database; @@ -64,11 +65,11 @@ public abstract class CustomLinkResolver implements LinkResolver /** temp dbs default to the filesystem, not in memory */ public static final boolean DEFAULT_IN_MEMORY = false; /** temp dbs end up in the system temp dir by default */ - public static final File DEFAULT_TEMP_DIR = null; + public static final Path DEFAULT_TEMP_DIR = null; private final FileFormat _defaultFormat; private final boolean _defaultInMemory; - private final File _defaultTempDir; + private final Path _defaultTempDir; /** * Creates a CustomLinkResolver using the default behavior for creating temp @@ -93,7 +94,7 @@ public abstract class CustomLinkResolver implements LinkResolver * directory) */ protected CustomLinkResolver(FileFormat defaultFormat, boolean defaultInMemory, - File defaultTempDir) + Path defaultTempDir) { _defaultFormat = defaultFormat; _defaultInMemory = defaultInMemory; @@ -108,7 +109,7 @@ public abstract class CustomLinkResolver implements LinkResolver return _defaultInMemory; } - protected File getDefaultTempDirectory() { + protected Path getDefaultTempDirectory() { return _defaultTempDir; } @@ -117,27 +118,27 @@ public abstract class CustomLinkResolver implements LinkResolver *
    *   // attempt to load the linkeeFileName as a custom file
    *   Object customFile = loadCustomFile(linkerDb, linkeeFileName);
-   *   
+   *
    *   if(customFile != null) {
    *     // this is a custom file, create and return relevant temp db
    *     return createTempDb(customFile, getDefaultFormat(), isDefaultInMemory(),
    *                         getDefaultTempDirectory());
    *   }
-   *   
+   *
    *   // not a custmom file, load using the default behavior
    *   return LinkResolver.DEFAULT.resolveLinkedDatabase(linkerDb, linkeeFileName);
    * 
- * + * * @see #loadCustomFile * @see #createTempDb * @see LinkResolver#DEFAULT */ public Database resolveLinkedDatabase(Database linkerDb, String linkeeFileName) - throws IOException + throws IOException { Object customFile = loadCustomFile(linkerDb, linkeeFileName); if(customFile != null) { - return createTempDb(customFile, getDefaultFormat(), isDefaultInMemory(), + return createTempDb(customFile, getDefaultFormat(), isDefaultInMemory(), getDefaultTempDirectory()); } return LinkResolver.DEFAULT.resolveLinkedDatabase(linkerDb, linkeeFileName); @@ -157,28 +158,30 @@ public abstract class CustomLinkResolver implements LinkResolver * * @return the temp db for holding the linked table info */ - protected Database createTempDb(Object customFile, FileFormat format, - boolean inMemory, File tempDir) + protected Database createTempDb(Object customFile, FileFormat format, + boolean inMemory, Path tempDir) throws IOException { - File dbFile = null; + Path dbFile = null; FileChannel channel = null; boolean success = false; try { if(inMemory) { - dbFile = new File(MEM_DB_PREFIX + DB_ID.nextLong() + - format.getFileExtension()); + dbFile = Paths.get(MEM_DB_PREFIX + DB_ID.nextLong() + + format.getFileExtension()); channel = MemFileChannel.newChannel(); } else { - dbFile = File.createTempFile(FILE_DB_PREFIX, format.getFileExtension(), - tempDir); - channel = new RandomAccessFile(dbFile, DatabaseImpl.RW_CHANNEL_MODE) - .getChannel(); + dbFile = ((tempDir != null) ? + Files.createTempFile(tempDir, FILE_DB_PREFIX, + format.getFileExtension()) : + Files.createTempFile(FILE_DB_PREFIX, + format.getFileExtension())); + channel = FileChannel.open(dbFile, DatabaseImpl.RW_CHANNEL_OPTS); } TempDatabaseImpl.initDbChannel(channel, format); - TempDatabaseImpl db = new TempDatabaseImpl(this, customFile, dbFile, + TempDatabaseImpl db = new TempDatabaseImpl(this, customFile, dbFile, channel, format); success = true; return db; @@ -192,9 +195,12 @@ public abstract class CustomLinkResolver implements LinkResolver } } - private static void deleteDbFile(File dbFile) { - if((dbFile != null) && (dbFile.getName().startsWith(FILE_DB_PREFIX))) { - dbFile.delete(); + private static void deleteDbFile(Path dbFile) { + if((dbFile != null) && + dbFile.getFileName().toString().startsWith(FILE_DB_PREFIX)) { + try { + Files.deleteIfExists(dbFile); + } catch(IOException ignores) {} } } @@ -203,7 +209,7 @@ public abstract class CustomLinkResolver implements LinkResolver ByteUtil.closeQuietly((Closeable)customFile); } } - + /** * Called by {@link #resolveLinkedDatabase} to determine whether the * linkeeFileName should be treated as a custom file (thus utiliziing a temp @@ -252,7 +258,7 @@ public abstract class CustomLinkResolver implements LinkResolver private final Object _customFile; protected TempDatabaseImpl(CustomLinkResolver resolver, Object customFile, - File file, FileChannel channel, + Path file, FileChannel channel, FileFormat fileFormat) throws IOException { @@ -262,11 +268,11 @@ public abstract class CustomLinkResolver implements LinkResolver } @Override - protected TableImpl getTable(String name, boolean includeSystemTables) - throws IOException + protected TableImpl getTable(String name, boolean includeSystemTables) + throws IOException { TableImpl table = super.getTable(name, includeSystemTables); - if((table == null) && + if((table == null) && _resolver.loadCustomTable(this, _customFile, name)) { table = super.getTable(name, includeSystemTables); } @@ -278,7 +284,7 @@ public abstract class CustomLinkResolver implements LinkResolver try { super.close(); } finally { - deleteDbFile(getFile()); + deleteDbFile(getPath()); closeCustomFile(_customFile); } } diff --git a/src/main/java/com/healthmarketscience/jackcess/util/MemFileChannel.java b/src/main/java/com/healthmarketscience/jackcess/util/MemFileChannel.java index 9ff542f..4420938 100644 --- a/src/main/java/com/healthmarketscience/jackcess/util/MemFileChannel.java +++ b/src/main/java/com/healthmarketscience/jackcess/util/MemFileChannel.java @@ -29,6 +29,9 @@ import java.nio.channels.FileLock; import java.nio.channels.NonWritableChannelException; import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel; +import java.nio.file.OpenOption; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; import com.healthmarketscience.jackcess.Database; import com.healthmarketscience.jackcess.DatabaseBuilder; @@ -53,8 +56,13 @@ import com.healthmarketscience.jackcess.impl.DatabaseImpl; * @author James Ahlborn * @usage _advanced_class_ */ -public class MemFileChannel extends FileChannel +public class MemFileChannel extends FileChannel { + /** read-only channel access mode */ + public static final String RO_CHANNEL_MODE = "r"; + /** read/write channel access mode */ + public static final String RW_CHANNEL_MODE = "rw"; + private static final byte[][] EMPTY_DATA = new byte[0][]; // use largest possible Jet "page size" to ensure that reads/writes will @@ -68,10 +76,10 @@ public class MemFileChannel extends FileChannel /** current amount of actual data in the file */ private long _size; /** chunks containing the file data. the length of the chunk array is - always a power of 2 and the chunks are always CHUNK_SIZE. */ + always a power of 2 and the chunks are always CHUNK_SIZE. */ private byte[][] _data; - private MemFileChannel() + private MemFileChannel() { this(0L, 0L, EMPTY_DATA); } @@ -95,7 +103,7 @@ public class MemFileChannel extends FileChannel * affect the original File source. */ public static MemFileChannel newChannel(File file) throws IOException { - return newChannel(file, DatabaseImpl.RW_CHANNEL_MODE); + return newChannel(file, RW_CHANNEL_MODE); } /** @@ -105,25 +113,62 @@ public class MemFileChannel extends FileChannel * modifications to the returned channel will not affect the original * File source. */ - public static MemFileChannel newChannel(File file, String mode) - throws IOException + public static MemFileChannel newChannel(File file, String mode) + throws IOException { FileChannel in = null; try { return newChannel(in = new RandomAccessFile( - file, DatabaseImpl.RO_CHANNEL_MODE).getChannel(), + file, RO_CHANNEL_MODE).getChannel(), + mode); + } finally { + ByteUtil.closeQuietly(in); + } + } + + /** + * Creates a new MemFileChannel containing the contents of the + * given Path with the given mode (for mode details see + * {@link RandomAccessFile#RandomAccessFile(File,String)}). Note, + * modifications to the returned channel will not affect the original + * File source. + */ + public static MemFileChannel newChannel(Path file, OpenOption... opts) + throws IOException + { + FileChannel in = null; + try { + String mode = RO_CHANNEL_MODE; + if(opts != null) { + for(OpenOption opt : opts) { + if(opt == StandardOpenOption.WRITE) { + mode = RW_CHANNEL_MODE; + break; + } + } + } + return newChannel(in = FileChannel.open(file, StandardOpenOption.READ), mode); } finally { ByteUtil.closeQuietly(in); } } + /** + * Creates a new read/write MemFileChannel containing the contents of the + * given Path. Note, modifications to the returned channel will not + * affect the original File source. + */ + public static MemFileChannel newChannel(Path file) throws IOException { + return newChannel(file, DatabaseImpl.RW_CHANNEL_OPTS); + } + /** * Creates a new read/write MemFileChannel containing the contents of the * given InputStream. */ public static MemFileChannel newChannel(InputStream in) throws IOException { - return newChannel(in, DatabaseImpl.RW_CHANNEL_MODE); + return newChannel(in, RW_CHANNEL_MODE); } /** @@ -131,8 +176,8 @@ public class MemFileChannel extends FileChannel * given InputStream with the given mode (for mode details see * {@link RandomAccessFile#RandomAccessFile(File,String)}). */ - public static MemFileChannel newChannel(InputStream in, String mode) - throws IOException + public static MemFileChannel newChannel(InputStream in, String mode) + throws IOException { return newChannel(Channels.newChannel(in), mode); } @@ -141,10 +186,10 @@ public class MemFileChannel extends FileChannel * Creates a new read/write MemFileChannel containing the contents of the * given ReadableByteChannel. */ - public static MemFileChannel newChannel(ReadableByteChannel in) + public static MemFileChannel newChannel(ReadableByteChannel in) throws IOException { - return newChannel(in, DatabaseImpl.RW_CHANNEL_MODE); + return newChannel(in, RW_CHANNEL_MODE); } /** @@ -152,7 +197,7 @@ public class MemFileChannel extends FileChannel * given ReadableByteChannel with the given mode (for mode details see * {@link RandomAccessFile#RandomAccessFile(File,String)}). */ - public static MemFileChannel newChannel(ReadableByteChannel in, String mode) + public static MemFileChannel newChannel(ReadableByteChannel in, String mode) throws IOException { MemFileChannel channel = new MemFileChannel(); @@ -282,7 +327,7 @@ public class MemFileChannel extends FileChannel if(position >= _size) { return 0L; } - + count = Math.min(count, _size - position); int chunkIndex = getChunkIndex(position); @@ -304,7 +349,7 @@ public class MemFileChannel extends FileChannel numBytes += bytesWritten; count -= bytesWritten; } while(src.hasRemaining()); - + ++chunkIndex; chunkOffset = 0; } @@ -360,11 +405,11 @@ public class MemFileChannel extends FileChannel count -= bytesRead; _size = Math.max(_size, position + numBytes); } while(dst.hasRemaining()); - + ++chunkIndex; - chunkOffset = 0; + chunkOffset = 0; } - + return numBytes; } @@ -410,7 +455,7 @@ public class MemFileChannel extends FileChannel private static int getChunkIndex(long pos) { return (int)(pos / CHUNK_SIZE); } - + private static int getChunkOffset(long pos) { return (int)(pos % CHUNK_SIZE); } @@ -418,7 +463,7 @@ public class MemFileChannel extends FileChannel private static int getNumChunks(long size) { return getChunkIndex(size + CHUNK_SIZE - 1); } - + @Override public long write(ByteBuffer[] srcs, int offset, int length) throws IOException @@ -433,7 +478,7 @@ public class MemFileChannel extends FileChannel @Override public long read(ByteBuffer[] dsts, int offset, int length) throws IOException - { + { long numBytes = 0L; for(int i = offset; i < offset + length; ++i) { if(_position >= _size) { @@ -474,7 +519,7 @@ public class MemFileChannel extends FileChannel { super(channel._position, channel._size, channel._data); } - + @Override public int write(ByteBuffer src, long position) throws IOException { throw new NonWritableChannelException(); @@ -491,6 +536,6 @@ public class MemFileChannel extends FileChannel throws IOException { throw new NonWritableChannelException(); - } + } } } diff --git a/src/test/java/com/healthmarketscience/jackcess/DatabaseTest.java b/src/test/java/com/healthmarketscience/jackcess/DatabaseTest.java index 025e180..2ce343b 100644 --- a/src/test/java/com/healthmarketscience/jackcess/DatabaseTest.java +++ b/src/test/java/com/healthmarketscience/jackcess/DatabaseTest.java @@ -51,7 +51,7 @@ import static com.healthmarketscience.jackcess.TestUtil.*; /** * @author Tim McCune */ -public class DatabaseTest extends TestCase +public class DatabaseTest extends TestCase { public DatabaseTest(String name) throws Exception { super(name); @@ -114,7 +114,7 @@ public class DatabaseTest extends TestCase db.close(); } } - + public void testReadDeletedRows() throws Exception { for (final TestDB testDB : TestDB.getSupportedForBasename(Basename.DEL, true)) { Table table = open(testDB).getTable("Table"); @@ -122,11 +122,11 @@ public class DatabaseTest extends TestCase while (table.getNextRow() != null) { rows++; } - assertEquals(2, rows); + assertEquals(2, rows); table.getDatabase().close(); } } - + public void testGetColumns() throws Exception { for (final TestDB testDB : SUPPORTED_DBS_TEST_FOR_READ) { @@ -143,9 +143,9 @@ public class DatabaseTest extends TestCase checkColumn(columns, 8, "I", DataType.BOOLEAN); } } - + private static void checkColumn( - List columns, int columnNumber, String name, + List columns, int columnNumber, String name, DataType dataType) throws Exception { @@ -153,7 +153,7 @@ public class DatabaseTest extends TestCase assertEquals(name, column.getName()); assertEquals(dataType, column.getType()); } - + public void testGetNextRow() throws Exception { for (final TestDB testDB : SUPPORTED_DBS_TEST_FOR_READ) { final Database db = open(testDB); @@ -183,7 +183,7 @@ public class DatabaseTest extends TestCase db.close(); } } - + public void testDeleteCurrentRow() throws Exception { // make sure correct row is deleted @@ -269,7 +269,7 @@ public class DatabaseTest extends TestCase table.reset(); List rows = RowFilterTest.toList(table); - + Row r1 = rows.remove(7); Row r2 = rows.remove(3); assertEquals(8, rows.size()); @@ -282,10 +282,10 @@ public class DatabaseTest extends TestCase table.deleteRow(r2); table.deleteRow(r1); - assertTable(rows, table); + assertTable(rows, table); } } - + public void testMissingFile() throws Exception { File bogusFile = new File("fooby-dooby.mdb"); assertTrue(!bogusFile.exists()); @@ -326,7 +326,7 @@ public class DatabaseTest extends TestCase } rowNum++; } - + table.getDatabase().close(); } } @@ -508,7 +508,7 @@ public class DatabaseTest extends TestCase db.close(); } - } + } public void testMultiPageTableDef() throws Exception { @@ -580,7 +580,7 @@ public class DatabaseTest extends TestCase db.close(); } - } + } public void testLargeTableDef() throws Exception { @@ -685,8 +685,8 @@ public class DatabaseTest extends TestCase TimeZone tz = TimeZone.getTimeZone("America/New_York"); SimpleDateFormat sdf = DatabaseBuilder.createDateFormat("yyyy-MM-dd"); sdf.getCalendar().setTimeZone(tz); - - List dates = Arrays.asList("1582-10-15", "1582-10-14", + + List dates = Arrays.asList("1582-10-15", "1582-10-14", "1492-01-10", "1392-01-10"); @@ -703,7 +703,7 @@ public class DatabaseTest extends TestCase Date d = sdf.parse(dateStr); table.addRow("row " + dateStr, d); } - + List foundDates = new ArrayList(); for(Row row : table) { foundDates.add(sdf.format(row.getDate("date"))); @@ -741,7 +741,7 @@ public class DatabaseTest extends TestCase sysTables.addAll( Arrays.asList("MSysObjects", "MSysQueries", "MSysACES", "MSysRelationships")); - + if (fileFormat == FileFormat.GENERIC_JET4) { assertNull("file format: " + fileFormat, db.getSystemTable("MSysAccessObjects")); } else if (fileFormat.ordinal() < FileFormat.V2003.ordinal()) { @@ -766,11 +766,11 @@ public class DatabaseTest extends TestCase if(fileFormat.ordinal() >= FileFormat.V2010.ordinal()) { sysTables.add("f_12D7448B56564D8AAE333BCC9B3718E5_Data"); sysTables.add("MSysResources"); - } + } } assertEquals(sysTables, db.getSystemTableNames()); - + assertNotNull(db.getSystemTable("MSysObjects")); assertNotNull(db.getSystemTable("MSysQueries")); assertNotNull(db.getSystemTable("MSysACES")); @@ -782,7 +782,7 @@ public class DatabaseTest extends TestCase assertEquals("MSysObjects", tmd.getName()); assertFalse(tmd.isLinked()); assertTrue(tmd.isSystem()); - + db.close(); } } @@ -839,7 +839,7 @@ public class DatabaseTest extends TestCase "RawData[(12) FF FE 6F 74 68 65 72 20 64 61 74 61]", null); List fixVals = Arrays.asList("RawData[(4) 37 00 00 00]", - "RawData[(4) F3 FF FF FF]", + "RawData[(4) F3 FF FF FF]", "RawData[(4) 02 00 00 00]"); int idx = 0; @@ -891,7 +891,8 @@ public class DatabaseTest extends TestCase Database linkeeDb = db.getLinkedDatabases().get(linkeeDbName); assertNotNull(linkeeDb); assertEquals(linkeeFile, linkeeDb.getFile()); - + assertEquals("linkeeTest.accdb", ((DatabaseImpl)linkeeDb).getName()); + List> expectedRows = createExpectedTable( createExpectedRow( @@ -900,7 +901,7 @@ public class DatabaseTest extends TestCase assertTable(expectedRows, t2); - db.createLinkedTable("FooTable", linkeeDbName, "Table2"); + db.createLinkedTable("FooTable", linkeeDbName, "Table2"); tmd = db.getTableMetaData("FooTable"); assertEquals("FooTable", tmd.getName()); @@ -929,7 +930,7 @@ public class DatabaseTest extends TestCase assertNull(tmd.getLinkedDbName()); Table t1 = tmd.open(db); - + assertFalse(db.isLinkedTable(null)); assertTrue(db.isLinkedTable(t2)); assertTrue(db.isLinkedTable(t3)); @@ -941,21 +942,21 @@ public class DatabaseTest extends TestCase assertTrue(tables.contains(t2)); assertTrue(tables.contains(t3)); assertFalse(tables.contains(((DatabaseImpl)db).getSystemCatalog())); - + tables = getTables(db.newIterable().setIncludeNormalTables(false)); assertEquals(2, tables.size()); assertFalse(tables.contains(t1)); assertTrue(tables.contains(t2)); assertTrue(tables.contains(t3)); assertFalse(tables.contains(((DatabaseImpl)db).getSystemCatalog())); - + tables = getTables(db.newIterable().withLocalUserTablesOnly()); assertEquals(1, tables.size()); assertTrue(tables.contains(t1)); assertFalse(tables.contains(t2)); assertFalse(tables.contains(t3)); assertFalse(tables.contains(((DatabaseImpl)db).getSystemCatalog())); - + tables = getTables(db.newIterable().withSystemTablesOnly()); assertTrue(tables.size() > 5); assertFalse(tables.contains(t1)); @@ -975,7 +976,7 @@ public class DatabaseTest extends TestCase } return tableList; } - + public void testTimeZone() throws Exception { TimeZone tz = TimeZone.getTimeZone("America/New_York"); diff --git a/src/test/java/com/healthmarketscience/jackcess/TestUtil.java b/src/test/java/com/healthmarketscience/jackcess/TestUtil.java index 7680fb3..0bef2e0 100644 --- a/src/test/java/com/healthmarketscience/jackcess/TestUtil.java +++ b/src/test/java/com/healthmarketscience/jackcess/TestUtil.java @@ -86,7 +86,7 @@ public class TestUtil throws Exception { FileChannel channel = (inMem ? MemFileChannel.newChannel( - file, DatabaseImpl.RW_CHANNEL_MODE) + file, MemFileChannel.RW_CHANNEL_MODE) : null); final Database db = new DatabaseBuilder(file).setReadOnly(true) .setAutoSync(getTestAutoSync()).setChannel(channel).open(); diff --git a/src/test/java/com/healthmarketscience/jackcess/impl/JetFormatTest.java b/src/test/java/com/healthmarketscience/jackcess/impl/JetFormatTest.java index 1ed17b7..36ab9bd 100644 --- a/src/test/java/com/healthmarketscience/jackcess/impl/JetFormatTest.java +++ b/src/test/java/com/healthmarketscience/jackcess/impl/JetFormatTest.java @@ -98,7 +98,7 @@ public class JetFormatTest extends TestCase { } SUPPORTED_FILEFORMATS = supported.toArray(new FileFormat[0]); - SUPPORTED_FILEFORMATS_FOR_READ = + SUPPORTED_FILEFORMATS_FOR_READ = supportedForRead.toArray(new FileFormat[0]); } @@ -110,7 +110,7 @@ public class JetFormatTest extends TestCase { private final File dbFile; private final FileFormat expectedFileFormat; - private TestDB(File databaseFile, + private TestDB(File databaseFile, FileFormat expectedDBFileFormat) { dbFile = databaseFile; @@ -119,12 +119,12 @@ public class JetFormatTest extends TestCase { public final File getFile() { return dbFile; } - public final FileFormat getExpectedFileFormat() { - return expectedFileFormat; + public final FileFormat getExpectedFileFormat() { + return expectedFileFormat; } - public final JetFormat getExpectedFormat() { - return DatabaseImpl.getFileFormatDetails(expectedFileFormat).getFormat(); + public final JetFormat getExpectedFormat() { + return DatabaseImpl.getFileFormatDetails(expectedFileFormat).getFormat(); } @Override @@ -141,14 +141,14 @@ public class JetFormatTest extends TestCase { boolean readOnly) { List supportedTestDBs = new ArrayList(); - for (FileFormat fileFormat : + for (FileFormat fileFormat : (readOnly ? SUPPORTED_FILEFORMATS_FOR_READ : SUPPORTED_FILEFORMATS)) { File testFile = getFileForBasename(basename, fileFormat); if(!testFile.exists()) { continue; } - + // verify that the db is the file format expected try { Database db = new DatabaseBuilder(testFile).setReadOnly(true).open(); @@ -170,16 +170,16 @@ public class JetFormatTest extends TestCase { private static File getFileForBasename( Basename basename, FileFormat fileFormat) { - return new File(DIR_TEST_DATA, + return new File(DIR_TEST_DATA, fileFormat.name() + File.separator + - basename + fileFormat.name() + + basename + fileFormat.name() + fileFormat.getFileExtension()); } } - public static final List SUPPORTED_DBS_TEST = + public static final List SUPPORTED_DBS_TEST = TestDB.getSupportedForBasename(Basename.TEST); - public static final List SUPPORTED_DBS_TEST_FOR_READ = + public static final List SUPPORTED_DBS_TEST_FOR_READ = TestDB.getSupportedForBasename(Basename.TEST, true); @@ -193,11 +193,12 @@ public class JetFormatTest extends TestCase { for (final TestDB testDB : SUPPORTED_DBS_TEST_FOR_READ) { - final FileChannel channel = DatabaseImpl.openChannel(testDB.dbFile, false); + final FileChannel channel = DatabaseImpl.openChannel( + testDB.dbFile.toPath(), false); try { JetFormat fmtActual = JetFormat.getFormat(channel); - assertEquals("Unexpected JetFormat for dbFile: " + + assertEquals("Unexpected JetFormat for dbFile: " + testDB.dbFile.getAbsolutePath(), testDB.getExpectedFormat(), fmtActual); @@ -221,7 +222,7 @@ public class JetFormatTest extends TestCase { PropertyMap props = db.getUserDefinedProperties(); props.put("foo", "bar"); props.save(); - } + } } catch(Exception e) { failure = e; @@ -268,7 +269,7 @@ public class JetFormatTest extends TestCase { } public void testSqlTypes() throws Exception { - + JetFormat v2000 = JetFormat.VERSION_4; for(DataType dt : DataType.values()) { if(v2000.isSupportedDataType(dt)) { diff --git a/src/test/java/com/healthmarketscience/jackcess/util/CustomLinkResolverTest.java b/src/test/java/com/healthmarketscience/jackcess/util/CustomLinkResolverTest.java index 31a8853..b2dfc06 100644 --- a/src/test/java/com/healthmarketscience/jackcess/util/CustomLinkResolverTest.java +++ b/src/test/java/com/healthmarketscience/jackcess/util/CustomLinkResolverTest.java @@ -16,9 +16,9 @@ limitations under the License. package com.healthmarketscience.jackcess.util; -import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; +import java.nio.file.Path; import com.healthmarketscience.jackcess.ColumnBuilder; import com.healthmarketscience.jackcess.DataType; @@ -55,7 +55,7 @@ public class CustomLinkResolverTest extends TestCase Table t1 = db.getTable("Table1"); assertNotNull(t1); assertNotSame(db, t1.getDatabase()); - + assertTable(createExpectedTable(createExpectedRow("id", 0, "data1", "row0"), createExpectedRow("id", 1, @@ -101,7 +101,7 @@ public class CustomLinkResolverTest extends TestCase Database linkerDb, String linkeeFileName) throws IOException { return (("testFile1.txt".equals(linkeeFileName) || - "testFile2.txt".equals(linkeeFileName)) ? + "testFile2.txt".equals(linkeeFileName)) ? linkeeFileName : null); } @@ -121,7 +121,7 @@ public class CustomLinkResolverTest extends TestCase for(int i = 0; i < 3; ++i) { t.addRow(i, "row" + i); } - + return true; } else if("OtherTable2".equals(tableName)) { @@ -135,7 +135,7 @@ public class CustomLinkResolverTest extends TestCase for(int i = 3; i < 6; ++i) { t.addRow(i, "row" + i); } - + return true; } else if("Table4".equals(tableName)) { @@ -149,7 +149,7 @@ public class CustomLinkResolverTest extends TestCase @Override protected Database createTempDb(Object customFile, FileFormat format, - boolean inMemory, File tempDir) + boolean inMemory, Path tempDir) throws IOException { inMemory = "testFile1.txt".equals(customFile); -- 2.39.5