Coverage Report - com.healthmarketscience.jackcess.JetFormat
 
Classes in this File Line Coverage Branch Coverage Complexity
JetFormat
96%
67/70
50%
2/4
0
JetFormat$1
N/A
N/A
0
JetFormat$Jet4Format
100%
58/58
N/A
0
 
 1  
 /*
 2  
 Copyright (c) 2005 Health Market Science, Inc.
 3  
 
 4  
 This library is free software; you can redistribute it and/or
 5  
 modify it under the terms of the GNU Lesser General Public
 6  
 License as published by the Free Software Foundation; either
 7  
 version 2.1 of the License, or (at your option) any later version.
 8  
 
 9  
 This library is distributed in the hope that it will be useful,
 10  
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 11  
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 12  
 Lesser General Public License for more details.
 13  
 
 14  
 You should have received a copy of the GNU Lesser General Public
 15  
 License along with this library; if not, write to the Free Software
 16  
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 17  
 USA
 18  
 
 19  
 You can contact Health Market Science at info@healthmarketscience.com
 20  
 or at the following address:
 21  
 
 22  
 Health Market Science
 23  
 2700 Horizon Drive
 24  
 Suite 200
 25  
 King of Prussia, PA 19406
 26  
 */
 27  
 
 28  
 package com.healthmarketscience.jackcess;
 29  
 
 30  
 import java.io.IOException;
 31  
 import java.nio.ByteBuffer;
 32  
 import java.nio.channels.FileChannel;
 33  
 import java.nio.charset.Charset;
 34  
 
 35  
 /**
 36  
  * Encapsulates constants describing a specific version of the Access Jet format
 37  
  * @author Tim McCune
 38  
  */
 39  1
 public abstract class JetFormat {
 40  
   
 41  
   /** Maximum size of a record minus OLE objects and Memo fields */
 42  
   public static final int MAX_RECORD_SIZE = 1900;  //2kb minus some overhead
 43  
 
 44  
   /** the "unit" size for text fields */
 45  
   public static final short TEXT_FIELD_UNIT_SIZE = 2;
 46  
   /** Maximum size of a text field */
 47  
   public static final short TEXT_FIELD_MAX_LENGTH = 255 * TEXT_FIELD_UNIT_SIZE;
 48  
   
 49  
   /** Offset in the file that holds the byte describing the Jet format version */
 50  
   private static final long OFFSET_VERSION = 20L;
 51  
   /** Version code for Jet version 3 */
 52  
   private static final byte CODE_VERSION_3 = 0x0;
 53  
   /** Version code for Jet version 4 */
 54  
   private static final byte CODE_VERSION_4 = 0x1;
 55  
 
 56  
   //These constants are populated by this class's constructor.  They can't be
 57  
   //populated by the subclass's constructor because they are final, and Java
 58  
   //doesn't allow this; hence all the abstract defineXXX() methods.
 59  
 
 60  
   /** the name of this format */
 61  
   private final String _name;
 62  
   
 63  
   /** Database page size in bytes */
 64  
   public final int PAGE_SIZE;
 65  
   public final long MAX_DATABASE_SIZE;
 66  
   
 67  
   public final int MAX_ROW_SIZE;
 68  
   public final int PAGE_INITIAL_FREE_SPACE;
 69  
   
 70  
   public final int OFFSET_NEXT_TABLE_DEF_PAGE;
 71  
   public final int OFFSET_NUM_ROWS;
 72  
   public final int OFFSET_NEXT_AUTO_NUMBER;
 73  
   public final int OFFSET_TABLE_TYPE;
 74  
   public final int OFFSET_MAX_COLS;
 75  
   public final int OFFSET_NUM_VAR_COLS;
 76  
   public final int OFFSET_NUM_COLS;
 77  
   public final int OFFSET_NUM_INDEX_SLOTS;
 78  
   public final int OFFSET_NUM_INDEXES;
 79  
   public final int OFFSET_OWNED_PAGES;
 80  
   public final int OFFSET_FREE_SPACE_PAGES;
 81  
   public final int OFFSET_INDEX_DEF_BLOCK;
 82  
   
 83  
   public final int OFFSET_INDEX_NUMBER_BLOCK;
 84  
   
 85  
   public final int OFFSET_COLUMN_TYPE;
 86  
   public final int OFFSET_COLUMN_NUMBER;
 87  
   public final int OFFSET_COLUMN_PRECISION;
 88  
   public final int OFFSET_COLUMN_SCALE;
 89  
   public final int OFFSET_COLUMN_FLAGS;
 90  
   public final int OFFSET_COLUMN_COMPRESSED_UNICODE;
 91  
   public final int OFFSET_COLUMN_LENGTH;
 92  
   public final int OFFSET_COLUMN_VARIABLE_TABLE_INDEX;
 93  
   public final int OFFSET_COLUMN_FIXED_DATA_OFFSET;
 94  
   
 95  
   public final int OFFSET_TABLE_DEF_LOCATION;
 96  
   
 97  
   public final int OFFSET_ROW_START;
 98  
   public final int OFFSET_USAGE_MAP_START;
 99  
   
 100  
   public final int OFFSET_USAGE_MAP_PAGE_DATA;
 101  
   
 102  
   public final int OFFSET_REFERENCE_MAP_PAGE_NUMBERS;
 103  
   
 104  
   public final int OFFSET_FREE_SPACE;
 105  
   public final int OFFSET_NUM_ROWS_ON_DATA_PAGE;
 106  
   public final int MAX_NUM_ROWS_ON_DATA_PAGE;
 107  
   
 108  
   public final int OFFSET_INDEX_COMPRESSED_BYTE_COUNT;
 109  
   public final int OFFSET_INDEX_ENTRY_MASK;
 110  
   public final int OFFSET_PREV_INDEX_PAGE;
 111  
   public final int OFFSET_NEXT_INDEX_PAGE;
 112  
   public final int OFFSET_CHILD_TAIL_INDEX_PAGE;
 113  
   
 114  
   public final int SIZE_INDEX_DEFINITION;
 115  
   public final int SIZE_COLUMN_HEADER;
 116  
   public final int SIZE_ROW_LOCATION;
 117  
   public final int SIZE_LONG_VALUE_DEF;
 118  
   public final int MAX_INLINE_LONG_VALUE_SIZE;
 119  
   public final int MAX_LONG_VALUE_ROW_SIZE;
 120  
   public final int SIZE_TDEF_HEADER;
 121  
   public final int SIZE_TDEF_TRAILER;
 122  
   public final int SIZE_COLUMN_DEF_BLOCK;
 123  
   public final int SIZE_INDEX_ENTRY_MASK;
 124  
   
 125  
   public final int USAGE_MAP_TABLE_BYTE_LENGTH;
 126  
 
 127  
   public final int MAX_COLUMNS_PER_TABLE;
 128  
   public final int MAX_TABLE_NAME_LENGTH;
 129  
   public final int MAX_COLUMN_NAME_LENGTH;
 130  
   public final int MAX_INDEX_NAME_LENGTH;
 131  
   
 132  
   public final Charset CHARSET;
 133  
   
 134  1
   public static final JetFormat VERSION_4 = new Jet4Format();
 135  
 
 136  
   /**
 137  
    * @return The Jet Format represented in the passed-in file
 138  
    */
 139  
   public static JetFormat getFormat(FileChannel channel) throws IOException {
 140  67
     ByteBuffer buffer = ByteBuffer.allocate(1);
 141  67
     int bytesRead = channel.read(buffer, OFFSET_VERSION);
 142  67
     if(bytesRead < 1) {
 143  0
       throw new IOException("Empty database file");
 144  
     }
 145  67
     buffer.flip();
 146  67
     byte version = buffer.get();
 147  67
     if (version == CODE_VERSION_4) {
 148  67
       return VERSION_4;
 149  
     }
 150  0
     throw new IOException("Unsupported version: " + version);
 151  
   }
 152  
   
 153  1
   private JetFormat(String name) {
 154  1
     _name = name;
 155  
     
 156  1
     PAGE_SIZE = definePageSize();
 157  1
     MAX_DATABASE_SIZE = defineMaxDatabaseSize();
 158  
     
 159  1
     MAX_ROW_SIZE = defineMaxRowSize();
 160  1
     PAGE_INITIAL_FREE_SPACE = definePageInitialFreeSpace();
 161  
     
 162  1
     OFFSET_NEXT_TABLE_DEF_PAGE = defineOffsetNextTableDefPage();
 163  1
     OFFSET_NUM_ROWS = defineOffsetNumRows();
 164  1
     OFFSET_NEXT_AUTO_NUMBER = defineOffsetNextAutoNumber();
 165  1
     OFFSET_TABLE_TYPE = defineOffsetTableType();
 166  1
     OFFSET_MAX_COLS = defineOffsetMaxCols();
 167  1
     OFFSET_NUM_VAR_COLS = defineOffsetNumVarCols();
 168  1
     OFFSET_NUM_COLS = defineOffsetNumCols();
 169  1
     OFFSET_NUM_INDEX_SLOTS = defineOffsetNumIndexSlots();
 170  1
     OFFSET_NUM_INDEXES = defineOffsetNumIndexes();
 171  1
     OFFSET_OWNED_PAGES = defineOffsetOwnedPages();
 172  1
     OFFSET_FREE_SPACE_PAGES = defineOffsetFreeSpacePages();
 173  1
     OFFSET_INDEX_DEF_BLOCK = defineOffsetIndexDefBlock();
 174  
     
 175  1
     OFFSET_INDEX_NUMBER_BLOCK = defineOffsetIndexNumberBlock();
 176  
     
 177  1
     OFFSET_COLUMN_TYPE = defineOffsetColumnType();
 178  1
     OFFSET_COLUMN_NUMBER = defineOffsetColumnNumber();
 179  1
     OFFSET_COLUMN_PRECISION = defineOffsetColumnPrecision();
 180  1
     OFFSET_COLUMN_SCALE = defineOffsetColumnScale();
 181  1
     OFFSET_COLUMN_FLAGS = defineOffsetColumnFlags();
 182  1
     OFFSET_COLUMN_COMPRESSED_UNICODE = defineOffsetColumnCompressedUnicode();
 183  1
     OFFSET_COLUMN_LENGTH = defineOffsetColumnLength();
 184  1
     OFFSET_COLUMN_VARIABLE_TABLE_INDEX = defineOffsetColumnVariableTableIndex();
 185  1
     OFFSET_COLUMN_FIXED_DATA_OFFSET = defineOffsetColumnFixedDataOffset();
 186  
     
 187  1
     OFFSET_TABLE_DEF_LOCATION = defineOffsetTableDefLocation();
 188  
     
 189  1
     OFFSET_ROW_START = defineOffsetRowStart();
 190  1
     OFFSET_USAGE_MAP_START = defineOffsetUsageMapStart();
 191  
     
 192  1
     OFFSET_USAGE_MAP_PAGE_DATA = defineOffsetUsageMapPageData();
 193  
     
 194  1
     OFFSET_REFERENCE_MAP_PAGE_NUMBERS = defineOffsetReferenceMapPageNumbers();
 195  
     
 196  1
     OFFSET_FREE_SPACE = defineOffsetFreeSpace();
 197  1
     OFFSET_NUM_ROWS_ON_DATA_PAGE = defineOffsetNumRowsOnDataPage();
 198  1
     MAX_NUM_ROWS_ON_DATA_PAGE = defineMaxNumRowsOnDataPage();
 199  
     
 200  1
     OFFSET_INDEX_COMPRESSED_BYTE_COUNT = defineOffsetIndexCompressedByteCount();
 201  1
     OFFSET_INDEX_ENTRY_MASK = defineOffsetIndexEntryMask();
 202  1
     OFFSET_PREV_INDEX_PAGE = defineOffsetPrevIndexPage();
 203  1
     OFFSET_NEXT_INDEX_PAGE = defineOffsetNextIndexPage();
 204  1
     OFFSET_CHILD_TAIL_INDEX_PAGE = defineOffsetChildTailIndexPage();
 205  
     
 206  1
     SIZE_INDEX_DEFINITION = defineSizeIndexDefinition();
 207  1
     SIZE_COLUMN_HEADER = defineSizeColumnHeader();
 208  1
     SIZE_ROW_LOCATION = defineSizeRowLocation();
 209  1
     SIZE_LONG_VALUE_DEF = defineSizeLongValueDef();
 210  1
     MAX_INLINE_LONG_VALUE_SIZE = defineMaxInlineLongValueSize();
 211  1
     MAX_LONG_VALUE_ROW_SIZE = defineMaxLongValueRowSize();
 212  1
     SIZE_TDEF_HEADER = defineSizeTdefHeader();
 213  1
     SIZE_TDEF_TRAILER = defineSizeTdefTrailer();
 214  1
     SIZE_COLUMN_DEF_BLOCK = defineSizeColumnDefBlock();
 215  1
     SIZE_INDEX_ENTRY_MASK = defineSizeIndexEntryMask();
 216  
     
 217  1
     USAGE_MAP_TABLE_BYTE_LENGTH = defineUsageMapTableByteLength();
 218  
 
 219  1
     MAX_COLUMNS_PER_TABLE = defineMaxColumnsPerTable();
 220  1
     MAX_TABLE_NAME_LENGTH = defineMaxTableNameLength();
 221  1
     MAX_COLUMN_NAME_LENGTH = defineMaxColumnNameLength();
 222  1
     MAX_INDEX_NAME_LENGTH = defineMaxIndexNameLength();
 223  
 
 224  
     
 225  1
     CHARSET = defineCharset();
 226  1
   }
 227  
   
 228  
   protected abstract int definePageSize();
 229  
   protected abstract long defineMaxDatabaseSize();
 230  
   
 231  
   protected abstract int defineMaxRowSize();
 232  
   protected abstract int definePageInitialFreeSpace();
 233  
   
 234  
   protected abstract int defineOffsetNextTableDefPage();
 235  
   protected abstract int defineOffsetNumRows();
 236  
   protected abstract int defineOffsetNextAutoNumber();
 237  
   protected abstract int defineOffsetTableType();
 238  
   protected abstract int defineOffsetMaxCols();
 239  
   protected abstract int defineOffsetNumVarCols();
 240  
   protected abstract int defineOffsetNumCols();
 241  
   protected abstract int defineOffsetNumIndexSlots();
 242  
   protected abstract int defineOffsetNumIndexes();
 243  
   protected abstract int defineOffsetOwnedPages();
 244  
   protected abstract int defineOffsetFreeSpacePages();
 245  
   protected abstract int defineOffsetIndexDefBlock();
 246  
   
 247  
   protected abstract int defineOffsetIndexNumberBlock();
 248  
   
 249  
   protected abstract int defineOffsetColumnType();
 250  
   protected abstract int defineOffsetColumnNumber();
 251  
   protected abstract int defineOffsetColumnPrecision();
 252  
   protected abstract int defineOffsetColumnScale();
 253  
   protected abstract int defineOffsetColumnFlags();
 254  
   protected abstract int defineOffsetColumnCompressedUnicode();
 255  
   protected abstract int defineOffsetColumnLength();
 256  
   protected abstract int defineOffsetColumnVariableTableIndex();
 257  
   protected abstract int defineOffsetColumnFixedDataOffset();
 258  
   
 259  
   protected abstract int defineOffsetTableDefLocation();
 260  
   
 261  
   protected abstract int defineOffsetRowStart();
 262  
   protected abstract int defineOffsetUsageMapStart();
 263  
   
 264  
   protected abstract int defineOffsetUsageMapPageData();
 265  
   
 266  
   protected abstract int defineOffsetReferenceMapPageNumbers();
 267  
   
 268  
   protected abstract int defineOffsetFreeSpace();
 269  
   protected abstract int defineOffsetNumRowsOnDataPage();
 270  
   protected abstract int defineMaxNumRowsOnDataPage();
 271  
   
 272  
   protected abstract int defineOffsetIndexCompressedByteCount();
 273  
   protected abstract int defineOffsetIndexEntryMask();
 274  
   protected abstract int defineOffsetPrevIndexPage();
 275  
   protected abstract int defineOffsetNextIndexPage();
 276  
   protected abstract int defineOffsetChildTailIndexPage();
 277  
   
 278  
   protected abstract int defineSizeIndexDefinition();
 279  
   protected abstract int defineSizeColumnHeader();
 280  
   protected abstract int defineSizeRowLocation();
 281  
   protected abstract int defineSizeLongValueDef();
 282  
   protected abstract int defineMaxInlineLongValueSize();
 283  
   protected abstract int defineMaxLongValueRowSize();
 284  
   protected abstract int defineSizeTdefHeader();
 285  
   protected abstract int defineSizeTdefTrailer();
 286  
   protected abstract int defineSizeColumnDefBlock();
 287  
   protected abstract int defineSizeIndexEntryMask();
 288  
   
 289  
   protected abstract int defineUsageMapTableByteLength();
 290  
 
 291  
   protected abstract int defineMaxColumnsPerTable();
 292  
   protected abstract int defineMaxTableNameLength();
 293  
   protected abstract int defineMaxColumnNameLength();
 294  
   protected abstract int defineMaxIndexNameLength();
 295  
   
 296  
   protected abstract Charset defineCharset();
 297  
 
 298  
   @Override
 299  
   public String toString() {
 300  0
     return _name;
 301  
   }
 302  
   
 303  1
   private static final class Jet4Format extends JetFormat {
 304  
 
 305  
     private Jet4Format() {
 306  1
       super("VERSION_4");
 307  1
     }
 308  
 
 309  
     @Override
 310  1
     protected int definePageSize() { return 4096; }
 311  
     
 312  
     @Override
 313  
     protected long defineMaxDatabaseSize() {
 314  1
       return (2L * 1024L * 1024L * 1024L);
 315  
     }
 316  
     
 317  
     @Override
 318  1
     protected int defineMaxRowSize() { return 4060; }
 319  
     @Override
 320  1
     protected int definePageInitialFreeSpace() { return PAGE_SIZE - 14; }
 321  
     
 322  
     @Override
 323  1
     protected int defineOffsetNextTableDefPage() { return 4; }
 324  
     @Override
 325  1
     protected int defineOffsetNumRows() { return 16; }
 326  
     @Override
 327  1
     protected int defineOffsetNextAutoNumber() { return 20; }
 328  
     @Override
 329  1
     protected int defineOffsetTableType() { return 40; }
 330  
     @Override
 331  1
     protected int defineOffsetMaxCols() { return 41; }
 332  
     @Override
 333  1
     protected int defineOffsetNumVarCols() { return 43; }
 334  
     @Override
 335  1
     protected int defineOffsetNumCols() { return 45; }
 336  
     @Override
 337  1
     protected int defineOffsetNumIndexSlots() { return 47; }
 338  
     @Override
 339  1
     protected int defineOffsetNumIndexes() { return 51; }
 340  
     @Override
 341  1
     protected int defineOffsetOwnedPages() { return 55; }
 342  
     @Override
 343  1
     protected int defineOffsetFreeSpacePages() { return 59; }
 344  
     @Override
 345  1
     protected int defineOffsetIndexDefBlock() { return 63; }
 346  
 
 347  
     @Override
 348  1
     protected int defineOffsetIndexNumberBlock() { return 52; }
 349  
     
 350  
     @Override
 351  1
     protected int defineOffsetColumnType() { return 0; }
 352  
     @Override
 353  1
     protected int defineOffsetColumnNumber() { return 5; }
 354  
     @Override
 355  1
     protected int defineOffsetColumnPrecision() { return 11; }
 356  
     @Override
 357  1
     protected int defineOffsetColumnScale() { return 12; }
 358  
     @Override
 359  1
     protected int defineOffsetColumnFlags() { return 15; }
 360  
     @Override
 361  1
     protected int defineOffsetColumnCompressedUnicode() { return 16; }
 362  
     @Override
 363  1
     protected int defineOffsetColumnLength() { return 23; }
 364  
     @Override
 365  1
     protected int defineOffsetColumnVariableTableIndex() { return 7; }
 366  
     @Override
 367  1
     protected int defineOffsetColumnFixedDataOffset() { return 21; }
 368  
   
 369  
     @Override
 370  1
     protected int defineOffsetTableDefLocation() { return 4; }
 371  
     
 372  
     @Override
 373  1
     protected int defineOffsetRowStart() { return 14; }
 374  
     @Override
 375  1
     protected int defineOffsetUsageMapStart() { return 5; }
 376  
     
 377  
     @Override
 378  1
     protected int defineOffsetUsageMapPageData() { return 4; }
 379  
     
 380  
     @Override
 381  1
     protected int defineOffsetReferenceMapPageNumbers() { return 1; }
 382  
     
 383  
     @Override
 384  1
     protected int defineOffsetFreeSpace() { return 2; }
 385  
     @Override
 386  1
     protected int defineOffsetNumRowsOnDataPage() { return 12; }
 387  
     @Override
 388  1
     protected int defineMaxNumRowsOnDataPage() { return 255; }
 389  
     
 390  
     @Override
 391  1
     protected int defineOffsetIndexCompressedByteCount() { return 24; }
 392  
     @Override
 393  1
     protected int defineOffsetIndexEntryMask() { return 27; }
 394  
     @Override
 395  1
     protected int defineOffsetPrevIndexPage() { return 12; }
 396  
     @Override
 397  1
     protected int defineOffsetNextIndexPage() { return 16; }
 398  
     @Override
 399  1
     protected int defineOffsetChildTailIndexPage() { return 20; }
 400  
     
 401  
     @Override
 402  1
     protected int defineSizeIndexDefinition() { return 12; }
 403  
     @Override
 404  1
     protected int defineSizeColumnHeader() { return 25; }
 405  
     @Override
 406  1
     protected int defineSizeRowLocation() { return 2; }
 407  
     @Override
 408  1
     protected int defineSizeLongValueDef() { return 12; }
 409  
     @Override
 410  1
     protected int defineMaxInlineLongValueSize() { return 64; }
 411  
     @Override
 412  1
     protected int defineMaxLongValueRowSize() { return 4076; }
 413  
     @Override
 414  1
     protected int defineSizeTdefHeader() { return 63; }
 415  
     @Override
 416  1
     protected int defineSizeTdefTrailer() { return 2; }
 417  
     @Override
 418  1
     protected int defineSizeColumnDefBlock() { return 25; }
 419  
     @Override
 420  1
     protected int defineSizeIndexEntryMask() { return 453; }
 421  
     
 422  
     @Override
 423  1
     protected int defineUsageMapTableByteLength() { return 64; }
 424  
       
 425  
     @Override
 426  1
     protected int defineMaxColumnsPerTable() { return 255; }
 427  
       
 428  
     @Override
 429  1
     protected int defineMaxTableNameLength() { return 64; }
 430  
       
 431  
     @Override
 432  1
     protected int defineMaxColumnNameLength() { return 64; }
 433  
       
 434  
     @Override
 435  1
     protected int defineMaxIndexNameLength() { return 64; }
 436  
       
 437  
     @Override
 438  1
     protected Charset defineCharset() { return Charset.forName("UTF-16LE"); }
 439  
   }
 440  
   
 441  
 }