summaryrefslogtreecommitdiffstats
path: root/src/java/com/healthmarketscience/jackcess/JetFormat.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/java/com/healthmarketscience/jackcess/JetFormat.java')
-rw-r--r--src/java/com/healthmarketscience/jackcess/JetFormat.java302
1 files changed, 302 insertions, 0 deletions
diff --git a/src/java/com/healthmarketscience/jackcess/JetFormat.java b/src/java/com/healthmarketscience/jackcess/JetFormat.java
new file mode 100644
index 0000000..561e417
--- /dev/null
+++ b/src/java/com/healthmarketscience/jackcess/JetFormat.java
@@ -0,0 +1,302 @@
+/*
+Copyright (c) 2005 Health Market Science, Inc.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+USA
+
+You can contact Health Market Science at info@healthmarketscience.com
+or at the following address:
+
+Health Market Science
+2700 Horizon Drive
+Suite 200
+King of Prussia, PA 19406
+*/
+
+package com.healthmarketscience.jackcess;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.charset.Charset;
+
+/**
+ * Encapsulates constants describing a specific version of the Access Jet format
+ * @author Tim McCune
+ */
+public abstract class JetFormat {
+
+ /** Maximum size of a record minus OLE objects and Memo fields */
+ public static final int MAX_RECORD_SIZE = 1900; //2kb minus some overhead
+
+ /** Maximum size of a text field */
+ public static final short TEXT_FIELD_MAX_LENGTH = 255 * 2;
+
+ /** Offset in the file that holds the byte describing the Jet format version */
+ private static final long OFFSET_VERSION = 20L;
+ /** Version code for Jet version 3 */
+ private static final byte CODE_VERSION_3 = 0x0;
+ /** Version code for Jet version 4 */
+ private static final byte CODE_VERSION_4 = 0x1;
+
+ //These constants are populated by this class's constructor. They can't be
+ //populated by the subclass's constructor because they are final, and Java
+ //doesn't allow this; hence all the abstract defineXXX() methods.
+
+ /** Database page size in bytes */
+ public final int PAGE_SIZE;
+
+ public final int MAX_ROW_SIZE;
+
+ public final int OFFSET_NEXT_TABLE_DEF_PAGE;
+ public final int OFFSET_NUM_ROWS;
+ public final int OFFSET_TABLE_TYPE;
+ public final int OFFSET_NUM_COLS;
+ public final int OFFSET_NUM_INDEXES;
+ public final int OFFSET_OWNED_PAGES;
+ public final int OFFSET_FREE_SPACE_PAGES;
+ public final int OFFSET_INDEX_DEF_BLOCK;
+
+ public final int OFFSET_COLUMN_TYPE;
+ public final int OFFSET_COLUMN_NUMBER;
+ public final int OFFSET_COLUMN_PRECISION;
+ public final int OFFSET_COLUMN_SCALE;
+ public final int OFFSET_COLUMN_VARIABLE;
+ public final int OFFSET_COLUMN_COMPRESSED_UNICODE;
+ public final int OFFSET_COLUMN_LENGTH;
+
+ public final int OFFSET_TABLE_DEF_LOCATION;
+ public final int OFFSET_NUM_ROWS_ON_PAGE;
+ public final int OFFSET_ROW_LOCATION_BLOCK;
+
+ public final int OFFSET_ROW_START;
+ public final int OFFSET_MAP_START;
+
+ public final int OFFSET_USAGE_MAP_PAGE_DATA;
+
+ public final int OFFSET_REFERENCE_MAP_PAGE_NUMBERS;
+
+ public final int OFFSET_FREE_SPACE;
+ public final int OFFSET_DATA_ROW_LOCATION_BLOCK;
+ public final int OFFSET_NUM_ROWS_ON_DATA_PAGE;
+
+ public final int OFFSET_LVAL_ROW_LOCATION_BLOCK;
+
+ public final int OFFSET_USED_PAGES_USAGE_MAP_DEF;
+ public final int OFFSET_FREE_PAGES_USAGE_MAP_DEF;
+
+ public final int OFFSET_INDEX_ENTRY_MASK;
+
+ public final int SIZE_INDEX_DEFINITION;
+ public final int SIZE_COLUMN_HEADER;
+ public final int SIZE_ROW_LOCATION;
+ public final int SIZE_LONG_VALUE_DEF;
+ public final int SIZE_TDEF_BLOCK;
+ public final int SIZE_COLUMN_DEF_BLOCK;
+ public final int SIZE_INDEX_ENTRY_MASK;
+
+ public final int PAGES_PER_USAGE_MAP_PAGE;
+
+ public final Charset CHARSET;
+
+ public static final JetFormat VERSION_4 = new Jet4Format();
+
+ /**
+ * @return The Jet Format represented in the passed-in file
+ */
+ public static JetFormat getFormat(FileChannel channel) throws IOException {
+ ByteBuffer buffer = ByteBuffer.allocate(1);
+ channel.read(buffer, OFFSET_VERSION);
+ buffer.flip();
+ byte version = buffer.get();
+ if (version == CODE_VERSION_4) {
+ return VERSION_4;
+ } else {
+ throw new IOException("Unsupported version: " + version);
+ }
+ }
+
+ private JetFormat() {
+
+ PAGE_SIZE = definePageSize();
+
+ MAX_ROW_SIZE = defineMaxRowSize();
+
+ OFFSET_NEXT_TABLE_DEF_PAGE = defineOffsetNextTableDefPage();
+ OFFSET_NUM_ROWS = defineOffsetNumRows();
+ OFFSET_TABLE_TYPE = defineOffsetTableType();
+ OFFSET_NUM_COLS = defineOffsetNumCols();
+ OFFSET_NUM_INDEXES = defineOffsetNumIndexes();
+ OFFSET_OWNED_PAGES = defineOffsetOwnedPages();
+ OFFSET_FREE_SPACE_PAGES = defineOffsetFreeSpacePages();
+ OFFSET_INDEX_DEF_BLOCK = defineOffsetIndexDefBlock();
+
+ OFFSET_COLUMN_TYPE = defineOffsetColumnType();
+ OFFSET_COLUMN_NUMBER = defineOffsetColumnNumber();
+ OFFSET_COLUMN_PRECISION = defineOffsetColumnPrecision();
+ OFFSET_COLUMN_SCALE = defineOffsetColumnScale();
+ OFFSET_COLUMN_VARIABLE = defineOffsetColumnVariable();
+ OFFSET_COLUMN_COMPRESSED_UNICODE = defineOffsetColumnCompressedUnicode();
+ OFFSET_COLUMN_LENGTH = defineOffsetColumnLength();
+
+ OFFSET_TABLE_DEF_LOCATION = defineOffsetTableDefLocation();
+ OFFSET_NUM_ROWS_ON_PAGE = defineOffsetNumRowsOnPage();
+ OFFSET_ROW_LOCATION_BLOCK = defineOffsetRowLocationBlock();
+
+ OFFSET_ROW_START = defineOffsetRowStart();
+ OFFSET_MAP_START = defineOffsetMapStart();
+
+ OFFSET_USAGE_MAP_PAGE_DATA = defineOffsetUsageMapPageData();
+
+ OFFSET_REFERENCE_MAP_PAGE_NUMBERS = defineOffsetReferenceMapPageNumbers();
+
+ OFFSET_FREE_SPACE = defineOffsetFreeSpace();
+ OFFSET_DATA_ROW_LOCATION_BLOCK = defineOffsetDataRowLocationBlock();
+ OFFSET_NUM_ROWS_ON_DATA_PAGE = defineOffsetNumRowsOnDataPage();
+
+ OFFSET_LVAL_ROW_LOCATION_BLOCK = defineOffsetLvalRowLocationBlock();
+
+ OFFSET_USED_PAGES_USAGE_MAP_DEF = defineOffsetUsedPagesUsageMapDef();
+ OFFSET_FREE_PAGES_USAGE_MAP_DEF = defineOffsetFreePagesUsageMapDef();
+
+ OFFSET_INDEX_ENTRY_MASK = defineOffsetIndexEntryMask();
+
+ SIZE_INDEX_DEFINITION = defineSizeIndexDefinition();
+ SIZE_COLUMN_HEADER = defineSizeColumnHeader();
+ SIZE_ROW_LOCATION = defineSizeRowLocation();
+ SIZE_LONG_VALUE_DEF = defineSizeLongValueDef();
+ SIZE_TDEF_BLOCK = defineSizeTdefBlock();
+ SIZE_COLUMN_DEF_BLOCK = defineSizeColumnDefBlock();
+ SIZE_INDEX_ENTRY_MASK = defineSizeIndexEntryMask();
+
+ PAGES_PER_USAGE_MAP_PAGE = definePagesPerUsageMapPage();
+
+ CHARSET = defineCharset();
+ }
+
+ protected abstract int definePageSize();
+
+ protected abstract int defineMaxRowSize();
+
+ protected abstract int defineOffsetNextTableDefPage();
+ protected abstract int defineOffsetNumRows();
+ protected abstract int defineOffsetTableType();
+ protected abstract int defineOffsetNumCols();
+ protected abstract int defineOffsetNumIndexes();
+ protected abstract int defineOffsetOwnedPages();
+ protected abstract int defineOffsetFreeSpacePages();
+ protected abstract int defineOffsetIndexDefBlock();
+
+ protected abstract int defineOffsetColumnType();
+ protected abstract int defineOffsetColumnNumber();
+ protected abstract int defineOffsetColumnPrecision();
+ protected abstract int defineOffsetColumnScale();
+ protected abstract int defineOffsetColumnVariable();
+ protected abstract int defineOffsetColumnCompressedUnicode();
+ protected abstract int defineOffsetColumnLength();
+
+ protected abstract int defineOffsetTableDefLocation();
+ protected abstract int defineOffsetNumRowsOnPage();
+ protected abstract int defineOffsetRowLocationBlock();
+
+ protected abstract int defineOffsetRowStart();
+ protected abstract int defineOffsetMapStart();
+
+ protected abstract int defineOffsetUsageMapPageData();
+
+ protected abstract int defineOffsetReferenceMapPageNumbers();
+
+ protected abstract int defineOffsetFreeSpace();
+ protected abstract int defineOffsetDataRowLocationBlock();
+ protected abstract int defineOffsetNumRowsOnDataPage();
+
+ protected abstract int defineOffsetLvalRowLocationBlock();
+
+ protected abstract int defineOffsetUsedPagesUsageMapDef();
+ protected abstract int defineOffsetFreePagesUsageMapDef();
+
+ protected abstract int defineOffsetIndexEntryMask();
+
+ protected abstract int defineSizeIndexDefinition();
+ protected abstract int defineSizeColumnHeader();
+ protected abstract int defineSizeRowLocation();
+ protected abstract int defineSizeLongValueDef();
+ protected abstract int defineSizeTdefBlock();
+ protected abstract int defineSizeColumnDefBlock();
+ protected abstract int defineSizeIndexEntryMask();
+
+ protected abstract int definePagesPerUsageMapPage();
+
+ protected abstract Charset defineCharset();
+
+ private static final class Jet4Format extends JetFormat {
+
+ protected int definePageSize() { return 4096; }
+
+ protected int defineMaxRowSize() { return PAGE_SIZE - 18; }
+
+ protected int defineOffsetNextTableDefPage() { return 4; }
+ protected int defineOffsetNumRows() { return 16; }
+ protected int defineOffsetTableType() { return 40; }
+ protected int defineOffsetNumCols() { return 45; }
+ protected int defineOffsetNumIndexes() { return 47; }
+ protected int defineOffsetOwnedPages() { return 55; }
+ protected int defineOffsetFreeSpacePages() { return 59; }
+ protected int defineOffsetIndexDefBlock() { return 63; }
+
+ protected int defineOffsetColumnType() { return 0; }
+ protected int defineOffsetColumnNumber() { return 5; }
+ protected int defineOffsetColumnPrecision() { return 11; }
+ protected int defineOffsetColumnScale() { return 12; }
+ protected int defineOffsetColumnVariable() { return 15; }
+ protected int defineOffsetColumnCompressedUnicode() { return 16; }
+ protected int defineOffsetColumnLength() { return 23; }
+
+ protected int defineOffsetTableDefLocation() { return 4; }
+ protected int defineOffsetNumRowsOnPage() { return 12; }
+ protected int defineOffsetRowLocationBlock() { return 16; }
+
+ protected int defineOffsetRowStart() { return 14; }
+ protected int defineOffsetMapStart() { return 5; }
+
+ protected int defineOffsetUsageMapPageData() { return 4; }
+
+ protected int defineOffsetReferenceMapPageNumbers() { return 1; }
+
+ protected int defineOffsetFreeSpace() { return 2; }
+ protected int defineOffsetDataRowLocationBlock() { return 14; }
+ protected int defineOffsetNumRowsOnDataPage() { return 12; }
+
+ protected int defineOffsetLvalRowLocationBlock() { return 10; }
+
+ protected int defineOffsetUsedPagesUsageMapDef() { return 4027; }
+ protected int defineOffsetFreePagesUsageMapDef() { return 3958; }
+
+ protected int defineOffsetIndexEntryMask() { return 27; }
+
+ protected int defineSizeIndexDefinition() { return 12; }
+ protected int defineSizeColumnHeader() { return 25; }
+ protected int defineSizeRowLocation() { return 2; }
+ protected int defineSizeLongValueDef() { return 12; }
+ protected int defineSizeTdefBlock() { return 63; }
+ protected int defineSizeColumnDefBlock() { return 25; }
+ protected int defineSizeIndexEntryMask() { return 453; }
+
+ protected int definePagesPerUsageMapPage() { return 4092 * 8; }
+
+ protected Charset defineCharset() { return Charset.forName("UTF-16LE"); }
+ }
+
+}