View Javadoc

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  import java.util.Collections;
35  import java.util.HashMap;
36  import java.util.Map;
37  
38  /**
39   * Encapsulates constants describing a specific version of the Access Jet format
40   * @author Tim McCune
41   */
42  public abstract class JetFormat {
43    
44    /** Maximum size of a record minus OLE objects and Memo fields */
45    public static final int MAX_RECORD_SIZE = 1900;  //2kb minus some overhead
46  
47    /** the "unit" size for text fields */
48    public static final short TEXT_FIELD_UNIT_SIZE = 2;
49    /** Maximum size of a text field */
50    public static final short TEXT_FIELD_MAX_LENGTH = 255 * TEXT_FIELD_UNIT_SIZE;
51  
52    public enum CodecType {
53      NONE, JET, MSISAM, OFFICE;
54    }
55    
56    /** Offset in the file that holds the byte describing the Jet format
57        version */
58    private static final int OFFSET_VERSION = 20;
59    /** Version code for Jet version 3 */
60    private static final byte CODE_VERSION_3 = 0x0;
61    /** Version code for Jet version 4 */
62    private static final byte CODE_VERSION_4 = 0x1;
63    /** Version code for Jet version 12 */
64    private static final byte CODE_VERSION_12 = 0x2;
65    /** Version code for Jet version 14 */
66    private static final byte CODE_VERSION_14 = 0x3;
67  
68    /** location of the engine name in the header */
69    static final int OFFSET_ENGINE_NAME = 0x4;
70    /** length of the engine name in the header */
71    static final int LENGTH_ENGINE_NAME = 0xF;
72    /** amount of initial data to be read to determine database type */
73    private static final int HEADER_LENGTH = 21;
74    
75    private final static byte[] MSISAM_ENGINE = new byte[] {
76      'M', 'S', 'I', 'S', 'A', 'M', ' ', 'D', 'a', 't', 'a', 'b', 'a', 's', 'e'
77    };
78  
79    /** mask used to obfuscate the db header */
80    private static final byte[] BASE_HEADER_MASK = new byte[]{
81      (byte)0xB5, (byte)0x6F, (byte)0x03, (byte)0x62, (byte)0x61, (byte)0x08,
82      (byte)0xC2, (byte)0x55, (byte)0xEB, (byte)0xA9, (byte)0x67, (byte)0x72,
83      (byte)0x43, (byte)0x3F, (byte)0x00, (byte)0x9C, (byte)0x7A, (byte)0x9F,
84      (byte)0x90, (byte)0xFF, (byte)0x80, (byte)0x9A, (byte)0x31, (byte)0xC5,
85      (byte)0x79, (byte)0xBA, (byte)0xED, (byte)0x30, (byte)0xBC, (byte)0xDF, 
86      (byte)0xCC, (byte)0x9D, (byte)0x63, (byte)0xD9, (byte)0xE4, (byte)0xC3,
87      (byte)0x7B, (byte)0x42, (byte)0xFB, (byte)0x8A, (byte)0xBC, (byte)0x4E,
88      (byte)0x86, (byte)0xFB, (byte)0xEC, (byte)0x37, (byte)0x5D, (byte)0x44,
89      (byte)0x9C, (byte)0xFA, (byte)0xC6, (byte)0x5E, (byte)0x28, (byte)0xE6, 
90      (byte)0x13, (byte)0xB6, (byte)0x8A, (byte)0x60, (byte)0x54, (byte)0x94,
91      (byte)0x7B, (byte)0x36, (byte)0xF5, (byte)0x72, (byte)0xDF, (byte)0xB1,
92      (byte)0x77, (byte)0xF4, (byte)0x13, (byte)0x43, (byte)0xCF, (byte)0xAF,
93      (byte)0xB1, (byte)0x33, (byte)0x34, (byte)0x61, (byte)0x79, (byte)0x5B,
94      (byte)0x92, (byte)0xB5, (byte)0x7C, (byte)0x2A, (byte)0x05, (byte)0xF1,
95      (byte)0x7C, (byte)0x99, (byte)0x01, (byte)0x1B, (byte)0x98, (byte)0xFD,
96      (byte)0x12, (byte)0x4F, (byte)0x4A, (byte)0x94, (byte)0x6C, (byte)0x3E,
97      (byte)0x60, (byte)0x26, (byte)0x5F, (byte)0x95, (byte)0xF8, (byte)0xD0,
98      (byte)0x89, (byte)0x24, (byte)0x85, (byte)0x67, (byte)0xC6, (byte)0x1F,
99      (byte)0x27, (byte)0x44, (byte)0xD2, (byte)0xEE, (byte)0xCF, (byte)0x65,
100     (byte)0xED, (byte)0xFF, (byte)0x07, (byte)0xC7, (byte)0x46, (byte)0xA1,
101     (byte)0x78, (byte)0x16, (byte)0x0C, (byte)0xED, (byte)0xE9, (byte)0x2D,
102     (byte)0x62, (byte)0xD4};    
103 
104   /** value of the "AccessVersion" property for access 2000 dbs:
105       {@code "08.50"} */
106   private static final String ACCESS_VERSION_2000 = "08.50";
107   /** value of the "AccessVersion" property for access 2002/2003 dbs
108       {@code "09.50"}  */
109   private static final String ACCESS_VERSION_2003 = "09.50";
110 
111   /** known intro bytes for property maps */
112   static final byte[][] PROPERTY_MAP_TYPES = {
113     new byte[]{'M', 'R', '2', '\0'}, // access 2000+
114     new byte[]{'K', 'K', 'D', '\0'}};  // access 97
115 
116   // use nested inner class to avoid problematic static init loops
117   private static final class PossibleFileFormats {
118     private static final Map<String,Database.FileFormat> POSSIBLE_VERSION_3 = 
119       Collections.singletonMap((String)null, Database.FileFormat.V1997);
120 
121     private static final Map<String,Database.FileFormat> POSSIBLE_VERSION_4 = 
122       new HashMap<String,Database.FileFormat>();
123 
124     private static final Map<String,Database.FileFormat> POSSIBLE_VERSION_12 = 
125       Collections.singletonMap((String)null, Database.FileFormat.V2007);
126 
127     private static final Map<String,Database.FileFormat> POSSIBLE_VERSION_14 = 
128       Collections.singletonMap((String)null, Database.FileFormat.V2010);
129 
130     private static final Map<String,Database.FileFormat> POSSIBLE_VERSION_MSISAM = 
131       Collections.singletonMap((String)null, Database.FileFormat.MSISAM);
132 
133     static {
134       POSSIBLE_VERSION_4.put(ACCESS_VERSION_2000, Database.FileFormat.V2000);
135       POSSIBLE_VERSION_4.put(ACCESS_VERSION_2003, Database.FileFormat.V2003);
136     }
137   }
138 
139   /** the JetFormat constants for the Jet database version "3" */
140   public static final JetFormat VERSION_3 = new Jet3Format();
141   /** the JetFormat constants for the Jet database version "4" */
142   public static final JetFormat VERSION_4 = new Jet4Format();
143   /** the JetFormat constants for the MSISAM database */
144   public static final JetFormat VERSION_MSISAM = new MSISAMFormat();
145   /** the JetFormat constants for the Jet database version "12" */
146   public static final JetFormat VERSION_12 = new Jet12Format();
147   /** the JetFormat constants for the Jet database version "14" */
148   public static final JetFormat VERSION_14 = new Jet14Format();
149 
150   //These constants are populated by this class's constructor.  They can't be
151   //populated by the subclass's constructor because they are final, and Java
152   //doesn't allow this; hence all the abstract defineXXX() methods.
153 
154   /** the name of this format */
155   private final String _name;
156   
157   /** the read/write mode of this format */
158   public final boolean READ_ONLY;
159   
160   /** whether or not we can use indexes in this format */
161   public final boolean INDEXES_SUPPORTED;
162 
163   /** type of page encoding supported */
164   public final CodecType CODEC_TYPE;
165   
166   /** Database page size in bytes */
167   public final int PAGE_SIZE;
168   public final long MAX_DATABASE_SIZE;
169   
170   public final int MAX_ROW_SIZE;
171   public final int DATA_PAGE_INITIAL_FREE_SPACE;
172 
173   public final int OFFSET_MASKED_HEADER;
174   public final byte[] HEADER_MASK;
175   public final int OFFSET_HEADER_DATE;
176   public final int OFFSET_PASSWORD;
177   public final int SIZE_PASSWORD;
178   public final int OFFSET_SORT_ORDER;
179   public final int SIZE_SORT_ORDER;
180   public final int OFFSET_CODE_PAGE;
181   public final int OFFSET_ENCODING_KEY;
182   public final int OFFSET_NEXT_TABLE_DEF_PAGE;
183   public final int OFFSET_NUM_ROWS;
184   public final int OFFSET_NEXT_AUTO_NUMBER;
185   public final int OFFSET_NEXT_COMPLEX_AUTO_NUMBER;
186   public final int OFFSET_TABLE_TYPE;
187   public final int OFFSET_MAX_COLS;
188   public final int OFFSET_NUM_VAR_COLS;
189   public final int OFFSET_NUM_COLS;
190   public final int OFFSET_NUM_INDEX_SLOTS;
191   public final int OFFSET_NUM_INDEXES;
192   public final int OFFSET_OWNED_PAGES;
193   public final int OFFSET_FREE_SPACE_PAGES;
194   public final int OFFSET_INDEX_DEF_BLOCK;
195   
196   public final int SIZE_INDEX_COLUMN_BLOCK;
197   public final int SIZE_INDEX_INFO_BLOCK;
198   
199   public final int OFFSET_COLUMN_TYPE;
200   public final int OFFSET_COLUMN_NUMBER;
201   public final int OFFSET_COLUMN_PRECISION;
202   public final int OFFSET_COLUMN_SCALE;
203   public final int OFFSET_COLUMN_SORT_ORDER;
204   public final int OFFSET_COLUMN_CODE_PAGE;
205   public final int OFFSET_COLUMN_COMPLEX_ID;
206   public final int OFFSET_COLUMN_FLAGS;
207   public final int OFFSET_COLUMN_COMPRESSED_UNICODE;
208   public final int OFFSET_COLUMN_LENGTH;
209   public final int OFFSET_COLUMN_VARIABLE_TABLE_INDEX;
210   public final int OFFSET_COLUMN_FIXED_DATA_OFFSET;
211   public final int OFFSET_COLUMN_FIXED_DATA_ROW_OFFSET;
212   
213   public final int OFFSET_TABLE_DEF_LOCATION;
214   
215   public final int OFFSET_ROW_START;
216   public final int OFFSET_USAGE_MAP_START;
217   
218   public final int OFFSET_USAGE_MAP_PAGE_DATA;
219   
220   public final int OFFSET_REFERENCE_MAP_PAGE_NUMBERS;
221   
222   public final int OFFSET_FREE_SPACE;
223   public final int OFFSET_NUM_ROWS_ON_DATA_PAGE;
224   public final int MAX_NUM_ROWS_ON_DATA_PAGE;
225   
226   public final int OFFSET_INDEX_COMPRESSED_BYTE_COUNT;
227   public final int OFFSET_INDEX_ENTRY_MASK;
228   public final int OFFSET_PREV_INDEX_PAGE;
229   public final int OFFSET_NEXT_INDEX_PAGE;
230   public final int OFFSET_CHILD_TAIL_INDEX_PAGE;
231   
232   public final int SIZE_INDEX_DEFINITION;
233   public final int SIZE_COLUMN_HEADER;
234   public final int SIZE_ROW_LOCATION;
235   public final int SIZE_LONG_VALUE_DEF;
236   public final int MAX_INLINE_LONG_VALUE_SIZE;
237   public final int MAX_LONG_VALUE_ROW_SIZE;
238   public final int MAX_COMPRESSED_UNICODE_SIZE;
239   public final int SIZE_TDEF_HEADER;
240   public final int SIZE_TDEF_TRAILER;
241   public final int SIZE_COLUMN_DEF_BLOCK;
242   public final int SIZE_INDEX_ENTRY_MASK;
243   public final int SKIP_BEFORE_INDEX_FLAGS;
244   public final int SKIP_AFTER_INDEX_FLAGS;
245   public final int SKIP_BEFORE_INDEX_SLOT;
246   public final int SKIP_AFTER_INDEX_SLOT;
247   public final int SKIP_BEFORE_INDEX;
248   public final int SIZE_NAME_LENGTH;
249   public final int SIZE_ROW_COLUMN_COUNT;
250   public final int SIZE_ROW_VAR_COL_OFFSET;
251   
252   public final int USAGE_MAP_TABLE_BYTE_LENGTH;
253 
254   public final int MAX_COLUMNS_PER_TABLE;
255   public final int MAX_TABLE_NAME_LENGTH;
256   public final int MAX_COLUMN_NAME_LENGTH;
257   public final int MAX_INDEX_NAME_LENGTH;
258 
259   public final boolean LEGACY_NUMERIC_INDEXES;
260   
261   public final Charset CHARSET;
262   public final Column.SortOrder DEFAULT_SORT_ORDER;
263   
264   /**
265    * @param channel the database file.
266    * @return The Jet Format represented in the passed-in file
267    * @throws IOException if the database file format is unsupported.
268    */
269   public static JetFormat getFormat(FileChannel channel) throws IOException {
270     ByteBuffer buffer = ByteBuffer.allocate(HEADER_LENGTH);
271     int bytesRead = channel.read(buffer, 0L);
272     if(bytesRead < HEADER_LENGTH) {
273       throw new IOException("Empty database file");
274     }
275     buffer.flip();
276     byte version = buffer.get(OFFSET_VERSION);
277     if (version == CODE_VERSION_3) {
278       return VERSION_3;
279     } else if (version == CODE_VERSION_4) {
280       if(ByteUtil.matchesRange(buffer, OFFSET_ENGINE_NAME, MSISAM_ENGINE)) {
281         return VERSION_MSISAM;
282       }
283       return VERSION_4;
284     } else if (version == CODE_VERSION_12) {
285       return VERSION_12;
286     } else if (version == CODE_VERSION_14) {
287       return VERSION_14;
288     }
289     throw new IOException("Unsupported " +
290                           ((version < CODE_VERSION_3) ? "older" : "newer") +
291                           " version: " + version);
292   }
293   
294   private JetFormat(String name) {
295     _name = name;
296     
297     READ_ONLY = defineReadOnly();
298     INDEXES_SUPPORTED = defineIndexesSupported();
299     CODEC_TYPE = defineCodecType();
300     
301     PAGE_SIZE = definePageSize();
302     MAX_DATABASE_SIZE = defineMaxDatabaseSize();
303     
304     MAX_ROW_SIZE = defineMaxRowSize();
305     DATA_PAGE_INITIAL_FREE_SPACE = defineDataPageInitialFreeSpace();
306     
307     OFFSET_MASKED_HEADER = defineOffsetMaskedHeader();
308     HEADER_MASK = defineHeaderMask();
309     OFFSET_HEADER_DATE = defineOffsetHeaderDate();
310     OFFSET_PASSWORD = defineOffsetPassword();
311     SIZE_PASSWORD = defineSizePassword();
312     OFFSET_SORT_ORDER = defineOffsetSortOrder();
313     SIZE_SORT_ORDER = defineSizeSortOrder();
314     OFFSET_CODE_PAGE = defineOffsetCodePage();
315     OFFSET_ENCODING_KEY = defineOffsetEncodingKey();
316     OFFSET_NEXT_TABLE_DEF_PAGE = defineOffsetNextTableDefPage();
317     OFFSET_NUM_ROWS = defineOffsetNumRows();
318     OFFSET_NEXT_AUTO_NUMBER = defineOffsetNextAutoNumber();
319     OFFSET_NEXT_COMPLEX_AUTO_NUMBER = defineOffsetNextComplexAutoNumber();
320     OFFSET_TABLE_TYPE = defineOffsetTableType();
321     OFFSET_MAX_COLS = defineOffsetMaxCols();
322     OFFSET_NUM_VAR_COLS = defineOffsetNumVarCols();
323     OFFSET_NUM_COLS = defineOffsetNumCols();
324     OFFSET_NUM_INDEX_SLOTS = defineOffsetNumIndexSlots();
325     OFFSET_NUM_INDEXES = defineOffsetNumIndexes();
326     OFFSET_OWNED_PAGES = defineOffsetOwnedPages();
327     OFFSET_FREE_SPACE_PAGES = defineOffsetFreeSpacePages();
328     OFFSET_INDEX_DEF_BLOCK = defineOffsetIndexDefBlock();
329     
330     SIZE_INDEX_COLUMN_BLOCK = defineSizeIndexColumnBlock();
331     SIZE_INDEX_INFO_BLOCK = defineSizeIndexInfoBlock();
332     
333     OFFSET_COLUMN_TYPE = defineOffsetColumnType();
334     OFFSET_COLUMN_NUMBER = defineOffsetColumnNumber();
335     OFFSET_COLUMN_PRECISION = defineOffsetColumnPrecision();
336     OFFSET_COLUMN_SCALE = defineOffsetColumnScale();
337     OFFSET_COLUMN_SORT_ORDER = defineOffsetColumnSortOrder();
338     OFFSET_COLUMN_CODE_PAGE = defineOffsetColumnCodePage();
339     OFFSET_COLUMN_COMPLEX_ID = defineOffsetColumnComplexId();
340     OFFSET_COLUMN_FLAGS = defineOffsetColumnFlags();
341     OFFSET_COLUMN_COMPRESSED_UNICODE = defineOffsetColumnCompressedUnicode();
342     OFFSET_COLUMN_LENGTH = defineOffsetColumnLength();
343     OFFSET_COLUMN_VARIABLE_TABLE_INDEX = defineOffsetColumnVariableTableIndex();
344     OFFSET_COLUMN_FIXED_DATA_OFFSET = defineOffsetColumnFixedDataOffset();
345     OFFSET_COLUMN_FIXED_DATA_ROW_OFFSET = defineOffsetColumnFixedDataRowOffset();
346     
347     OFFSET_TABLE_DEF_LOCATION = defineOffsetTableDefLocation();
348     
349     OFFSET_ROW_START = defineOffsetRowStart();
350     OFFSET_USAGE_MAP_START = defineOffsetUsageMapStart();
351     
352     OFFSET_USAGE_MAP_PAGE_DATA = defineOffsetUsageMapPageData();
353     
354     OFFSET_REFERENCE_MAP_PAGE_NUMBERS = defineOffsetReferenceMapPageNumbers();
355     
356     OFFSET_FREE_SPACE = defineOffsetFreeSpace();
357     OFFSET_NUM_ROWS_ON_DATA_PAGE = defineOffsetNumRowsOnDataPage();
358     MAX_NUM_ROWS_ON_DATA_PAGE = defineMaxNumRowsOnDataPage();
359     
360     OFFSET_INDEX_COMPRESSED_BYTE_COUNT = defineOffsetIndexCompressedByteCount();
361     OFFSET_INDEX_ENTRY_MASK = defineOffsetIndexEntryMask();
362     OFFSET_PREV_INDEX_PAGE = defineOffsetPrevIndexPage();
363     OFFSET_NEXT_INDEX_PAGE = defineOffsetNextIndexPage();
364     OFFSET_CHILD_TAIL_INDEX_PAGE = defineOffsetChildTailIndexPage();
365     
366     SIZE_INDEX_DEFINITION = defineSizeIndexDefinition();
367     SIZE_COLUMN_HEADER = defineSizeColumnHeader();
368     SIZE_ROW_LOCATION = defineSizeRowLocation();
369     SIZE_LONG_VALUE_DEF = defineSizeLongValueDef();
370     MAX_INLINE_LONG_VALUE_SIZE = defineMaxInlineLongValueSize();
371     MAX_LONG_VALUE_ROW_SIZE = defineMaxLongValueRowSize();
372     MAX_COMPRESSED_UNICODE_SIZE = defineMaxCompressedUnicodeSize();
373     SIZE_TDEF_HEADER = defineSizeTdefHeader();
374     SIZE_TDEF_TRAILER = defineSizeTdefTrailer();
375     SIZE_COLUMN_DEF_BLOCK = defineSizeColumnDefBlock();
376     SIZE_INDEX_ENTRY_MASK = defineSizeIndexEntryMask();
377     SKIP_BEFORE_INDEX_FLAGS = defineSkipBeforeIndexFlags();
378     SKIP_AFTER_INDEX_FLAGS = defineSkipAfterIndexFlags();
379     SKIP_BEFORE_INDEX_SLOT = defineSkipBeforeIndexSlot();
380     SKIP_AFTER_INDEX_SLOT = defineSkipAfterIndexSlot();
381     SKIP_BEFORE_INDEX = defineSkipBeforeIndex();
382     SIZE_NAME_LENGTH = defineSizeNameLength();
383     SIZE_ROW_COLUMN_COUNT = defineSizeRowColumnCount();
384     SIZE_ROW_VAR_COL_OFFSET = defineSizeRowVarColOffset();
385 
386     USAGE_MAP_TABLE_BYTE_LENGTH = defineUsageMapTableByteLength();
387 
388     MAX_COLUMNS_PER_TABLE = defineMaxColumnsPerTable();
389     MAX_TABLE_NAME_LENGTH = defineMaxTableNameLength();
390     MAX_COLUMN_NAME_LENGTH = defineMaxColumnNameLength();
391     MAX_INDEX_NAME_LENGTH = defineMaxIndexNameLength();
392     
393     LEGACY_NUMERIC_INDEXES = defineLegacyNumericIndexes();
394     
395     CHARSET = defineCharset();
396     DEFAULT_SORT_ORDER = defineDefaultSortOrder();
397   }
398   
399   protected abstract boolean defineReadOnly();
400   protected abstract boolean defineIndexesSupported();
401   protected abstract CodecType defineCodecType();
402   
403   protected abstract int definePageSize();
404   protected abstract long defineMaxDatabaseSize();
405   
406   protected abstract int defineMaxRowSize();
407   protected abstract int defineDataPageInitialFreeSpace();
408   
409   protected abstract int defineOffsetMaskedHeader();
410   protected abstract byte[] defineHeaderMask();
411   protected abstract int defineOffsetHeaderDate();
412   protected abstract int defineOffsetPassword();
413   protected abstract int defineSizePassword();
414   protected abstract int defineOffsetSortOrder();
415   protected abstract int defineSizeSortOrder();
416   protected abstract int defineOffsetCodePage();
417   protected abstract int defineOffsetEncodingKey();
418   protected abstract int defineOffsetNextTableDefPage();
419   protected abstract int defineOffsetNumRows();
420   protected abstract int defineOffsetNextAutoNumber();
421   protected abstract int defineOffsetNextComplexAutoNumber();
422   protected abstract int defineOffsetTableType();
423   protected abstract int defineOffsetMaxCols();
424   protected abstract int defineOffsetNumVarCols();
425   protected abstract int defineOffsetNumCols();
426   protected abstract int defineOffsetNumIndexSlots();
427   protected abstract int defineOffsetNumIndexes();
428   protected abstract int defineOffsetOwnedPages();
429   protected abstract int defineOffsetFreeSpacePages();
430   protected abstract int defineOffsetIndexDefBlock();
431   
432   protected abstract int defineSizeIndexColumnBlock();
433   protected abstract int defineSizeIndexInfoBlock();
434   
435   protected abstract int defineOffsetColumnType();
436   protected abstract int defineOffsetColumnNumber();
437   protected abstract int defineOffsetColumnPrecision();
438   protected abstract int defineOffsetColumnScale();
439   protected abstract int defineOffsetColumnSortOrder();
440   protected abstract int defineOffsetColumnCodePage();
441   protected abstract int defineOffsetColumnComplexId();
442   protected abstract int defineOffsetColumnFlags();
443   protected abstract int defineOffsetColumnCompressedUnicode();
444   protected abstract int defineOffsetColumnLength();
445   protected abstract int defineOffsetColumnVariableTableIndex();
446   protected abstract int defineOffsetColumnFixedDataOffset();
447   protected abstract int defineOffsetColumnFixedDataRowOffset();
448   
449   protected abstract int defineOffsetTableDefLocation();
450   
451   protected abstract int defineOffsetRowStart();
452   protected abstract int defineOffsetUsageMapStart();
453   
454   protected abstract int defineOffsetUsageMapPageData();
455   
456   protected abstract int defineOffsetReferenceMapPageNumbers();
457   
458   protected abstract int defineOffsetFreeSpace();
459   protected abstract int defineOffsetNumRowsOnDataPage();
460   protected abstract int defineMaxNumRowsOnDataPage();
461   
462   protected abstract int defineOffsetIndexCompressedByteCount();
463   protected abstract int defineOffsetIndexEntryMask();
464   protected abstract int defineOffsetPrevIndexPage();
465   protected abstract int defineOffsetNextIndexPage();
466   protected abstract int defineOffsetChildTailIndexPage();
467   
468   protected abstract int defineSizeIndexDefinition();
469   protected abstract int defineSizeColumnHeader();
470   protected abstract int defineSizeRowLocation();
471   protected abstract int defineSizeLongValueDef();
472   protected abstract int defineMaxInlineLongValueSize();
473   protected abstract int defineMaxLongValueRowSize();
474   protected abstract int defineMaxCompressedUnicodeSize();
475   protected abstract int defineSizeTdefHeader();
476   protected abstract int defineSizeTdefTrailer();
477   protected abstract int defineSizeColumnDefBlock();
478   protected abstract int defineSizeIndexEntryMask();
479   protected abstract int defineSkipBeforeIndexFlags();
480   protected abstract int defineSkipAfterIndexFlags();
481   protected abstract int defineSkipBeforeIndexSlot();
482   protected abstract int defineSkipAfterIndexSlot();
483   protected abstract int defineSkipBeforeIndex();
484   protected abstract int defineSizeNameLength();
485   protected abstract int defineSizeRowColumnCount();
486   protected abstract int defineSizeRowVarColOffset();
487 
488   protected abstract int defineUsageMapTableByteLength();
489 
490   protected abstract int defineMaxColumnsPerTable();
491   protected abstract int defineMaxTableNameLength();
492   protected abstract int defineMaxColumnNameLength();
493   protected abstract int defineMaxIndexNameLength();
494   
495   protected abstract Charset defineCharset();
496   protected abstract Column.SortOrder defineDefaultSortOrder();
497 
498   protected abstract boolean defineLegacyNumericIndexes();
499 
500   protected abstract Map<String,Database.FileFormat> getPossibleFileFormats();
501 
502   protected abstract boolean isSupportedDataType(DataType type);
503 
504   @Override
505   public String toString() {
506     return _name;
507   }
508   
509   private static class Jet3Format extends JetFormat {
510 
511     private Jet3Format() {
512       super("VERSION_3");
513     }
514 
515     @Override
516     protected boolean defineReadOnly() { return true; }
517 	    
518     @Override
519     protected boolean defineIndexesSupported() { return false; }
520 
521     @Override
522     protected CodecType defineCodecType() { 
523       return CodecType.JET; 
524     }
525 	    
526     @Override
527     protected int definePageSize() { return 2048; }
528 	    
529     @Override
530     protected long defineMaxDatabaseSize() {
531       return (1L * 1024L * 1024L * 1024L);
532     }
533 	    
534     @Override
535     protected int defineMaxRowSize() { return 2012; }
536     @Override
537     protected int defineDataPageInitialFreeSpace() { return PAGE_SIZE - 14; }
538 	    
539     @Override
540     protected int defineOffsetMaskedHeader() { return 24; }
541     @Override
542     protected byte[] defineHeaderMask() { 
543       return ByteUtil.copyOf(BASE_HEADER_MASK, BASE_HEADER_MASK.length - 2); 
544     }
545     @Override
546     protected int defineOffsetHeaderDate() { return -1; }
547     @Override
548     protected int defineOffsetPassword() { return 66; }
549     @Override
550     protected int defineSizePassword() { return 20; }
551     @Override
552     protected int defineOffsetSortOrder() { return 58; }
553     @Override
554     protected int defineSizeSortOrder() { return 2; }
555     @Override
556     protected int defineOffsetCodePage() { return 60; }
557     @Override
558     protected int defineOffsetEncodingKey() { return 62; }
559     @Override
560     protected int defineOffsetNextTableDefPage() { return 4; }
561     @Override
562     protected int defineOffsetNumRows() { return 12; }
563     @Override
564     protected int defineOffsetNextAutoNumber() { return 20; }
565     @Override
566     protected int defineOffsetNextComplexAutoNumber() { return -1; }
567     @Override
568     protected int defineOffsetTableType() { return 20; }
569     @Override
570     protected int defineOffsetMaxCols() { return 21; }
571     @Override
572     protected int defineOffsetNumVarCols() { return 23; }
573     @Override
574     protected int defineOffsetNumCols() { return 25; }
575     @Override
576     protected int defineOffsetNumIndexSlots() { return 27; }
577     @Override
578     protected int defineOffsetNumIndexes() { return 31; }
579     @Override
580     protected int defineOffsetOwnedPages() { return 35; }
581     @Override
582     protected int defineOffsetFreeSpacePages() { return 39; }
583     @Override
584     protected int defineOffsetIndexDefBlock() { return 43; }
585 
586     @Override
587     protected int defineSizeIndexColumnBlock() { return 39; }
588     @Override
589     protected int defineSizeIndexInfoBlock() { return 20; }
590 	    
591     @Override
592     protected int defineOffsetColumnType() { return 0; }
593     @Override
594     protected int defineOffsetColumnNumber() { return 1; }
595     @Override
596     protected int defineOffsetColumnPrecision() { return 11; }
597     @Override
598     protected int defineOffsetColumnScale() { return 12; }
599     @Override
600     protected int defineOffsetColumnSortOrder() { return 9; }
601     @Override
602     protected int defineOffsetColumnCodePage() { return 11; }
603     @Override
604     protected int defineOffsetColumnComplexId() { return -1; }
605     @Override
606     protected int defineOffsetColumnFlags() { return 13; }
607     @Override
608     protected int defineOffsetColumnCompressedUnicode() { return 16; }
609     @Override
610     protected int defineOffsetColumnLength() { return 16; }
611     @Override
612     protected int defineOffsetColumnVariableTableIndex() { return 3; }
613     @Override
614     protected int defineOffsetColumnFixedDataOffset() { return 14; }
615     @Override
616     protected int defineOffsetColumnFixedDataRowOffset() { return 1; }
617 	  
618     @Override
619     protected int defineOffsetTableDefLocation() { return 4; }
620 	    
621     @Override
622     protected int defineOffsetRowStart() { return 10; }
623     @Override
624     protected int defineOffsetUsageMapStart() { return 5; }
625 	    
626     @Override
627     protected int defineOffsetUsageMapPageData() { return 4; }
628 	    
629     @Override
630     protected int defineOffsetReferenceMapPageNumbers() { return 1; }
631 	    
632     @Override
633     protected int defineOffsetFreeSpace() { return 2; }
634     @Override
635     protected int defineOffsetNumRowsOnDataPage() { return 8; }
636     @Override
637     protected int defineMaxNumRowsOnDataPage() { return 255; }
638 	    
639     @Override
640     protected int defineOffsetIndexCompressedByteCount() { return 20; }
641     @Override
642     protected int defineOffsetIndexEntryMask() { return 22; }
643     @Override
644     protected int defineOffsetPrevIndexPage() { return 8; }
645     @Override
646     protected int defineOffsetNextIndexPage() { return 12; }
647     @Override
648     protected int defineOffsetChildTailIndexPage() { return 16; }
649 	    
650     @Override
651     protected int defineSizeIndexDefinition() { return 8; }
652     @Override
653     protected int defineSizeColumnHeader() { return 18; }
654     @Override
655     protected int defineSizeRowLocation() { return 2; }
656     @Override
657     protected int defineSizeLongValueDef() { return 12; }
658     @Override
659     protected int defineMaxInlineLongValueSize() { return 64; }
660     @Override
661     protected int defineMaxLongValueRowSize() { return 2032; }
662     @Override
663     protected int defineMaxCompressedUnicodeSize() { return 1024; }
664     @Override
665     protected int defineSizeTdefHeader() { return 63; }
666     @Override
667     protected int defineSizeTdefTrailer() { return 2; }
668     @Override
669     protected int defineSizeColumnDefBlock() { return 25; }
670     @Override
671     protected int defineSizeIndexEntryMask() { return 226; }
672     @Override
673     protected int defineSkipBeforeIndexFlags() { return 0; }
674     @Override
675     protected int defineSkipAfterIndexFlags() { return 0; }
676     @Override
677     protected int defineSkipBeforeIndexSlot() { return 0; }
678     @Override
679     protected int defineSkipAfterIndexSlot() { return 0; }
680     @Override
681     protected int defineSkipBeforeIndex() { return 0; }
682     @Override
683     protected int defineSizeNameLength() { return 1; }
684     @Override
685     protected int defineSizeRowColumnCount() { return 1; }
686     @Override
687     protected int defineSizeRowVarColOffset() { return 1; }
688 	    
689     @Override
690     protected int defineUsageMapTableByteLength() { return 128; }
691 	      
692     @Override
693     protected int defineMaxColumnsPerTable() { return 255; }
694 	      
695     @Override
696     protected int defineMaxTableNameLength() { return 64; }
697 	      
698     @Override
699     protected int defineMaxColumnNameLength() { return 64; }
700 	      
701     @Override
702     protected int defineMaxIndexNameLength() { return 64; }
703 	      
704     @Override
705     protected boolean defineLegacyNumericIndexes() { return true; }
706 
707     @Override
708     protected Charset defineCharset() { return Charset.defaultCharset(); }
709 
710     @Override
711     protected Column.SortOrder defineDefaultSortOrder() {
712       return Column.GENERAL_LEGACY_SORT_ORDER;
713     }
714 
715     @Override
716     protected Map<String,Database.FileFormat> getPossibleFileFormats()
717     {
718       return PossibleFileFormats.POSSIBLE_VERSION_3;
719     }
720 
721     @Override
722     protected boolean isSupportedDataType(DataType type) {
723       return (type != DataType.COMPLEX_TYPE);
724     }
725   }
726   
727   private static class Jet4Format extends JetFormat {
728 
729     private Jet4Format() {
730       this("VERSION_4");
731     }
732 
733     private Jet4Format(String name) {
734       super(name);
735     }
736 
737     @Override
738     protected boolean defineReadOnly() { return false; }
739     
740     @Override
741     protected boolean defineIndexesSupported() { return true; }
742 	    
743     @Override
744     protected CodecType defineCodecType() { 
745       return CodecType.JET; 
746     }
747 
748     @Override
749     protected int definePageSize() { return 4096; }
750     
751     @Override
752     protected long defineMaxDatabaseSize() {
753       return (2L * 1024L * 1024L * 1024L);
754     }
755     
756     @Override
757     protected int defineMaxRowSize() { return 4060; }
758     @Override
759     protected int defineDataPageInitialFreeSpace() { return PAGE_SIZE - 14; }
760     
761     @Override
762     protected int defineOffsetMaskedHeader() { return 24; }
763     @Override
764     protected byte[] defineHeaderMask() { return BASE_HEADER_MASK; }
765     @Override
766     protected int defineOffsetHeaderDate() { return 114; }
767     @Override
768     protected int defineOffsetPassword() { return 66; }
769     @Override
770     protected int defineSizePassword() { return 40; }
771     @Override
772     protected int defineOffsetSortOrder() { return 110; }
773     @Override
774     protected int defineSizeSortOrder() { return 4; }
775     @Override
776     protected int defineOffsetCodePage() { return 60; }
777     @Override
778     protected int defineOffsetEncodingKey() { return 62; }
779     @Override
780     protected int defineOffsetNextTableDefPage() { return 4; }
781     @Override
782     protected int defineOffsetNumRows() { return 16; }
783     @Override
784     protected int defineOffsetNextAutoNumber() { return 20; }
785     @Override
786     protected int defineOffsetNextComplexAutoNumber() { return -1; }
787     @Override
788     protected int defineOffsetTableType() { return 40; }
789     @Override
790     protected int defineOffsetMaxCols() { return 41; }
791     @Override
792     protected int defineOffsetNumVarCols() { return 43; }
793     @Override
794     protected int defineOffsetNumCols() { return 45; }
795     @Override
796     protected int defineOffsetNumIndexSlots() { return 47; }
797     @Override
798     protected int defineOffsetNumIndexes() { return 51; }
799     @Override
800     protected int defineOffsetOwnedPages() { return 55; }
801     @Override
802     protected int defineOffsetFreeSpacePages() { return 59; }
803     @Override
804     protected int defineOffsetIndexDefBlock() { return 63; }
805 
806     @Override
807     protected int defineSizeIndexColumnBlock() { return 52; }
808     @Override
809     protected int defineSizeIndexInfoBlock() { return 28; }
810     
811     @Override
812     protected int defineOffsetColumnType() { return 0; }
813     @Override
814     protected int defineOffsetColumnNumber() { return 5; }
815     @Override
816     protected int defineOffsetColumnPrecision() { return 11; }
817     @Override
818     protected int defineOffsetColumnScale() { return 12; }
819     @Override
820     protected int defineOffsetColumnSortOrder() { return 11; }
821     @Override
822     protected int defineOffsetColumnCodePage() { return -1; }
823     @Override
824     protected int defineOffsetColumnComplexId() { return -1; }
825     @Override
826     protected int defineOffsetColumnFlags() { return 15; }
827     @Override
828     protected int defineOffsetColumnCompressedUnicode() { return 16; }
829     @Override
830     protected int defineOffsetColumnLength() { return 23; }
831     @Override
832     protected int defineOffsetColumnVariableTableIndex() { return 7; }
833     @Override
834     protected int defineOffsetColumnFixedDataOffset() { return 21; }
835     @Override
836     protected int defineOffsetColumnFixedDataRowOffset() { return 2; }
837   
838     @Override
839     protected int defineOffsetTableDefLocation() { return 4; }
840     
841     @Override
842     protected int defineOffsetRowStart() { return 14; }
843     @Override
844     protected int defineOffsetUsageMapStart() { return 5; }
845     
846     @Override
847     protected int defineOffsetUsageMapPageData() { return 4; }
848     
849     @Override
850     protected int defineOffsetReferenceMapPageNumbers() { return 1; }
851     
852     @Override
853     protected int defineOffsetFreeSpace() { return 2; }
854     @Override
855     protected int defineOffsetNumRowsOnDataPage() { return 12; }
856     @Override
857     protected int defineMaxNumRowsOnDataPage() { return 255; }
858     
859     @Override
860     protected int defineOffsetIndexCompressedByteCount() { return 24; }
861     @Override
862     protected int defineOffsetIndexEntryMask() { return 27; }
863     @Override
864     protected int defineOffsetPrevIndexPage() { return 12; }
865     @Override
866     protected int defineOffsetNextIndexPage() { return 16; }
867     @Override
868     protected int defineOffsetChildTailIndexPage() { return 20; }
869     
870     @Override
871     protected int defineSizeIndexDefinition() { return 12; }
872     @Override
873     protected int defineSizeColumnHeader() { return 25; }
874     @Override
875     protected int defineSizeRowLocation() { return 2; }
876     @Override
877     protected int defineSizeLongValueDef() { return 12; }
878     @Override
879     protected int defineMaxInlineLongValueSize() { return 64; }
880     @Override
881     protected int defineMaxLongValueRowSize() { return 4076; }
882     @Override
883     protected int defineMaxCompressedUnicodeSize() { return 1024; }
884     @Override
885     protected int defineSizeTdefHeader() { return 63; }
886     @Override
887     protected int defineSizeTdefTrailer() { return 2; }
888     @Override
889     protected int defineSizeColumnDefBlock() { return 25; }
890     @Override
891     protected int defineSizeIndexEntryMask() { return 453; }
892     @Override
893     protected int defineSkipBeforeIndexFlags() { return 4; }
894     @Override
895     protected int defineSkipAfterIndexFlags() { return 5; }
896     @Override
897     protected int defineSkipBeforeIndexSlot() { return 4; }
898     @Override
899     protected int defineSkipAfterIndexSlot() { return 4; }
900     @Override
901     protected int defineSkipBeforeIndex() { return 4; }
902     @Override
903     protected int defineSizeNameLength() { return 2; }
904     @Override
905     protected int defineSizeRowColumnCount() { return 2; }
906     @Override
907     protected int defineSizeRowVarColOffset() { return 2; }
908     
909     @Override
910     protected int defineUsageMapTableByteLength() { return 64; }
911       
912     @Override
913     protected int defineMaxColumnsPerTable() { return 255; }
914       
915     @Override
916     protected int defineMaxTableNameLength() { return 64; }
917       
918     @Override
919     protected int defineMaxColumnNameLength() { return 64; }
920       
921     @Override
922     protected int defineMaxIndexNameLength() { return 64; }
923       
924     @Override
925     protected boolean defineLegacyNumericIndexes() { return true; }
926 
927     @Override
928     protected Charset defineCharset() { return Charset.forName("UTF-16LE"); }
929 
930     @Override
931     protected Column.SortOrder defineDefaultSortOrder() {
932       return Column.GENERAL_LEGACY_SORT_ORDER;
933     }
934 
935     @Override
936     protected Map<String,Database.FileFormat> getPossibleFileFormats()
937     {
938       return PossibleFileFormats.POSSIBLE_VERSION_4;
939     }
940 
941     @Override
942     protected boolean isSupportedDataType(DataType type) {
943       return (type != DataType.COMPLEX_TYPE);
944     }
945   }
946   
947   private static final class MSISAMFormat extends Jet4Format {
948     private MSISAMFormat() {
949       super("MSISAM");
950     }
951 
952     @Override
953     protected CodecType defineCodecType() { 
954       return CodecType.MSISAM; 
955     }
956 
957     @Override
958     protected Map<String,Database.FileFormat> getPossibleFileFormats()
959     {
960       return PossibleFileFormats.POSSIBLE_VERSION_MSISAM;
961     }
962   }
963 
964   private static class Jet12Format extends Jet4Format {
965     private Jet12Format() {
966       super("VERSION_12");
967     }
968 
969 
970     private Jet12Format(String name) {
971       super(name);
972     }
973 
974     @Override
975     protected CodecType defineCodecType() { 
976       return CodecType.OFFICE; 
977     }
978 
979     @Override
980     protected boolean defineLegacyNumericIndexes() { return false; }
981 
982     @Override
983     protected Map<String,Database.FileFormat> getPossibleFileFormats() {
984       return PossibleFileFormats.POSSIBLE_VERSION_12;
985     }
986 
987     @Override
988     protected int defineOffsetNextComplexAutoNumber() { return 28; }
989 
990     @Override
991     protected int defineOffsetColumnComplexId() { return 11; }
992     
993     @Override
994     protected boolean isSupportedDataType(DataType type) {
995       return true;
996     }
997   }
998 
999   private static final class Jet14Format extends Jet12Format {
1000       private Jet14Format() {
1001         super("VERSION_14");
1002       }
1003 
1004     @Override
1005     protected Column.SortOrder defineDefaultSortOrder() {
1006       return Column.GENERAL_SORT_ORDER;
1007     }
1008 
1009     @Override
1010     protected Map<String,Database.FileFormat> getPossibleFileFormats() {
1011       return PossibleFileFormats.POSSIBLE_VERSION_14;
1012     }
1013   }
1014 
1015 }