You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

JetFormat.java 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. /*
  2. Copyright (c) 2005 Health Market Science, Inc.
  3. This library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Lesser General Public
  5. License as published by the Free Software Foundation; either
  6. version 2.1 of the License, or (at your option) any later version.
  7. This library is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public
  12. License along with this library; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  14. USA
  15. You can contact Health Market Science at info@healthmarketscience.com
  16. or at the following address:
  17. Health Market Science
  18. 2700 Horizon Drive
  19. Suite 200
  20. King of Prussia, PA 19406
  21. */
  22. package com.healthmarketscience.jackcess;
  23. import java.io.File;
  24. import java.io.FileNotFoundException;
  25. import java.io.IOException;
  26. import java.nio.ByteBuffer;
  27. import java.nio.channels.FileChannel;
  28. import java.nio.charset.Charset;
  29. /**
  30. * Encapsulates constants describing a specific version of the Access Jet format
  31. * @author Tim McCune
  32. */
  33. public abstract class JetFormat {
  34. /** Maximum size of a record minus OLE objects and Memo fields */
  35. public static final int MAX_RECORD_SIZE = 1900; //2kb minus some overhead
  36. /** Maximum size of a text field */
  37. public static final short TEXT_FIELD_MAX_LENGTH = 255 * 2;
  38. /** Offset in the file that holds the byte describing the Jet format version */
  39. private static final long OFFSET_VERSION = 20L;
  40. /** Version code for Jet version 3 */
  41. private static final byte CODE_VERSION_3 = 0x0;
  42. /** Version code for Jet version 4 */
  43. private static final byte CODE_VERSION_4 = 0x1;
  44. //These constants are populated by this class's constructor. They can't be
  45. //populated by the subclass's constructor because they are final, and Java
  46. //doesn't allow this; hence all the abstract defineXXX() methods.
  47. /** Database page size in bytes */
  48. public final int PAGE_SIZE;
  49. public final int MAX_ROW_SIZE;
  50. public final int OFFSET_NEXT_TABLE_DEF_PAGE;
  51. public final int OFFSET_NUM_ROWS;
  52. public final int OFFSET_TABLE_TYPE;
  53. public final int OFFSET_NUM_COLS;
  54. public final int OFFSET_NUM_INDEXES;
  55. public final int OFFSET_OWNED_PAGES;
  56. public final int OFFSET_FREE_SPACE_PAGES;
  57. public final int OFFSET_INDEX_DEF_BLOCK;
  58. public final int OFFSET_COLUMN_TYPE;
  59. public final int OFFSET_COLUMN_NUMBER;
  60. public final int OFFSET_COLUMN_PRECISION;
  61. public final int OFFSET_COLUMN_SCALE;
  62. public final int OFFSET_COLUMN_VARIABLE;
  63. public final int OFFSET_COLUMN_COMPRESSED_UNICODE;
  64. public final int OFFSET_COLUMN_LENGTH;
  65. public final int OFFSET_TABLE_DEF_LOCATION;
  66. public final int OFFSET_NUM_ROWS_ON_PAGE;
  67. public final int OFFSET_ROW_LOCATION_BLOCK;
  68. public final int OFFSET_ROW_START;
  69. public final int OFFSET_MAP_START;
  70. public final int OFFSET_USAGE_MAP_PAGE_DATA;
  71. public final int OFFSET_REFERENCE_MAP_PAGE_NUMBERS;
  72. public final int OFFSET_FREE_SPACE;
  73. public final int OFFSET_DATA_ROW_LOCATION_BLOCK;
  74. public final int OFFSET_NUM_ROWS_ON_DATA_PAGE;
  75. public final int OFFSET_LVAL_ROW_LOCATION_BLOCK;
  76. public final int OFFSET_USED_PAGES_USAGE_MAP_DEF;
  77. public final int OFFSET_FREE_PAGES_USAGE_MAP_DEF;
  78. public final int OFFSET_INDEX_ENTRY_MASK;
  79. public final int SIZE_INDEX_DEFINITION;
  80. public final int SIZE_COLUMN_HEADER;
  81. public final int SIZE_ROW_LOCATION;
  82. public final int SIZE_LONG_VALUE_DEF;
  83. public final int SIZE_TDEF_BLOCK;
  84. public final int SIZE_COLUMN_DEF_BLOCK;
  85. public final int SIZE_INDEX_ENTRY_MASK;
  86. public final int PAGES_PER_USAGE_MAP_PAGE;
  87. public final Charset CHARSET;
  88. public static final JetFormat VERSION_4 = new Jet4Format();
  89. /**
  90. * @return <code>true</code> if the given file could possibly be a database
  91. * file.
  92. */
  93. public static boolean mayBeMdbFile(File file) throws IOException
  94. {
  95. // no chance of reading the file format if none of these is true
  96. return(file.exists() && file.canRead() && (file.length() >= 1L));
  97. }
  98. /**
  99. * @return The Jet Format represented in the passed-in file
  100. */
  101. public static JetFormat getFormat(FileChannel channel) throws IOException {
  102. ByteBuffer buffer = ByteBuffer.allocate(1);
  103. int bytesRead = channel.read(buffer, OFFSET_VERSION);
  104. buffer.flip();
  105. byte version = buffer.get();
  106. if (version == CODE_VERSION_4) {
  107. return VERSION_4;
  108. } else {
  109. throw new IOException("Unsupported version: " + version);
  110. }
  111. }
  112. private JetFormat() {
  113. PAGE_SIZE = definePageSize();
  114. MAX_ROW_SIZE = defineMaxRowSize();
  115. OFFSET_NEXT_TABLE_DEF_PAGE = defineOffsetNextTableDefPage();
  116. OFFSET_NUM_ROWS = defineOffsetNumRows();
  117. OFFSET_TABLE_TYPE = defineOffsetTableType();
  118. OFFSET_NUM_COLS = defineOffsetNumCols();
  119. OFFSET_NUM_INDEXES = defineOffsetNumIndexes();
  120. OFFSET_OWNED_PAGES = defineOffsetOwnedPages();
  121. OFFSET_FREE_SPACE_PAGES = defineOffsetFreeSpacePages();
  122. OFFSET_INDEX_DEF_BLOCK = defineOffsetIndexDefBlock();
  123. OFFSET_COLUMN_TYPE = defineOffsetColumnType();
  124. OFFSET_COLUMN_NUMBER = defineOffsetColumnNumber();
  125. OFFSET_COLUMN_PRECISION = defineOffsetColumnPrecision();
  126. OFFSET_COLUMN_SCALE = defineOffsetColumnScale();
  127. OFFSET_COLUMN_VARIABLE = defineOffsetColumnVariable();
  128. OFFSET_COLUMN_COMPRESSED_UNICODE = defineOffsetColumnCompressedUnicode();
  129. OFFSET_COLUMN_LENGTH = defineOffsetColumnLength();
  130. OFFSET_TABLE_DEF_LOCATION = defineOffsetTableDefLocation();
  131. OFFSET_NUM_ROWS_ON_PAGE = defineOffsetNumRowsOnPage();
  132. OFFSET_ROW_LOCATION_BLOCK = defineOffsetRowLocationBlock();
  133. OFFSET_ROW_START = defineOffsetRowStart();
  134. OFFSET_MAP_START = defineOffsetMapStart();
  135. OFFSET_USAGE_MAP_PAGE_DATA = defineOffsetUsageMapPageData();
  136. OFFSET_REFERENCE_MAP_PAGE_NUMBERS = defineOffsetReferenceMapPageNumbers();
  137. OFFSET_FREE_SPACE = defineOffsetFreeSpace();
  138. OFFSET_DATA_ROW_LOCATION_BLOCK = defineOffsetDataRowLocationBlock();
  139. OFFSET_NUM_ROWS_ON_DATA_PAGE = defineOffsetNumRowsOnDataPage();
  140. OFFSET_LVAL_ROW_LOCATION_BLOCK = defineOffsetLvalRowLocationBlock();
  141. OFFSET_USED_PAGES_USAGE_MAP_DEF = defineOffsetUsedPagesUsageMapDef();
  142. OFFSET_FREE_PAGES_USAGE_MAP_DEF = defineOffsetFreePagesUsageMapDef();
  143. OFFSET_INDEX_ENTRY_MASK = defineOffsetIndexEntryMask();
  144. SIZE_INDEX_DEFINITION = defineSizeIndexDefinition();
  145. SIZE_COLUMN_HEADER = defineSizeColumnHeader();
  146. SIZE_ROW_LOCATION = defineSizeRowLocation();
  147. SIZE_LONG_VALUE_DEF = defineSizeLongValueDef();
  148. SIZE_TDEF_BLOCK = defineSizeTdefBlock();
  149. SIZE_COLUMN_DEF_BLOCK = defineSizeColumnDefBlock();
  150. SIZE_INDEX_ENTRY_MASK = defineSizeIndexEntryMask();
  151. PAGES_PER_USAGE_MAP_PAGE = definePagesPerUsageMapPage();
  152. CHARSET = defineCharset();
  153. }
  154. protected abstract int definePageSize();
  155. protected abstract int defineMaxRowSize();
  156. protected abstract int defineOffsetNextTableDefPage();
  157. protected abstract int defineOffsetNumRows();
  158. protected abstract int defineOffsetTableType();
  159. protected abstract int defineOffsetNumCols();
  160. protected abstract int defineOffsetNumIndexes();
  161. protected abstract int defineOffsetOwnedPages();
  162. protected abstract int defineOffsetFreeSpacePages();
  163. protected abstract int defineOffsetIndexDefBlock();
  164. protected abstract int defineOffsetColumnType();
  165. protected abstract int defineOffsetColumnNumber();
  166. protected abstract int defineOffsetColumnPrecision();
  167. protected abstract int defineOffsetColumnScale();
  168. protected abstract int defineOffsetColumnVariable();
  169. protected abstract int defineOffsetColumnCompressedUnicode();
  170. protected abstract int defineOffsetColumnLength();
  171. protected abstract int defineOffsetTableDefLocation();
  172. protected abstract int defineOffsetNumRowsOnPage();
  173. protected abstract int defineOffsetRowLocationBlock();
  174. protected abstract int defineOffsetRowStart();
  175. protected abstract int defineOffsetMapStart();
  176. protected abstract int defineOffsetUsageMapPageData();
  177. protected abstract int defineOffsetReferenceMapPageNumbers();
  178. protected abstract int defineOffsetFreeSpace();
  179. protected abstract int defineOffsetDataRowLocationBlock();
  180. protected abstract int defineOffsetNumRowsOnDataPage();
  181. protected abstract int defineOffsetLvalRowLocationBlock();
  182. protected abstract int defineOffsetUsedPagesUsageMapDef();
  183. protected abstract int defineOffsetFreePagesUsageMapDef();
  184. protected abstract int defineOffsetIndexEntryMask();
  185. protected abstract int defineSizeIndexDefinition();
  186. protected abstract int defineSizeColumnHeader();
  187. protected abstract int defineSizeRowLocation();
  188. protected abstract int defineSizeLongValueDef();
  189. protected abstract int defineSizeTdefBlock();
  190. protected abstract int defineSizeColumnDefBlock();
  191. protected abstract int defineSizeIndexEntryMask();
  192. protected abstract int definePagesPerUsageMapPage();
  193. protected abstract Charset defineCharset();
  194. private static final class Jet4Format extends JetFormat {
  195. protected int definePageSize() { return 4096; }
  196. protected int defineMaxRowSize() { return PAGE_SIZE - 18; }
  197. protected int defineOffsetNextTableDefPage() { return 4; }
  198. protected int defineOffsetNumRows() { return 16; }
  199. protected int defineOffsetTableType() { return 40; }
  200. protected int defineOffsetNumCols() { return 45; }
  201. protected int defineOffsetNumIndexes() { return 51; }
  202. protected int defineOffsetOwnedPages() { return 55; }
  203. protected int defineOffsetFreeSpacePages() { return 59; }
  204. protected int defineOffsetIndexDefBlock() { return 63; }
  205. protected int defineOffsetColumnType() { return 0; }
  206. protected int defineOffsetColumnNumber() { return 5; }
  207. protected int defineOffsetColumnPrecision() { return 11; }
  208. protected int defineOffsetColumnScale() { return 12; }
  209. protected int defineOffsetColumnVariable() { return 15; }
  210. protected int defineOffsetColumnCompressedUnicode() { return 16; }
  211. protected int defineOffsetColumnLength() { return 23; }
  212. protected int defineOffsetTableDefLocation() { return 4; }
  213. protected int defineOffsetNumRowsOnPage() { return 12; }
  214. protected int defineOffsetRowLocationBlock() { return 16; }
  215. protected int defineOffsetRowStart() { return 14; }
  216. protected int defineOffsetMapStart() { return 5; }
  217. protected int defineOffsetUsageMapPageData() { return 4; }
  218. protected int defineOffsetReferenceMapPageNumbers() { return 1; }
  219. protected int defineOffsetFreeSpace() { return 2; }
  220. protected int defineOffsetDataRowLocationBlock() { return 14; }
  221. protected int defineOffsetNumRowsOnDataPage() { return 12; }
  222. protected int defineOffsetLvalRowLocationBlock() { return 10; }
  223. protected int defineOffsetUsedPagesUsageMapDef() { return 4027; }
  224. protected int defineOffsetFreePagesUsageMapDef() { return 3958; }
  225. protected int defineOffsetIndexEntryMask() { return 27; }
  226. protected int defineSizeIndexDefinition() { return 12; }
  227. protected int defineSizeColumnHeader() { return 25; }
  228. protected int defineSizeRowLocation() { return 2; }
  229. protected int defineSizeLongValueDef() { return 12; }
  230. protected int defineSizeTdefBlock() { return 63; }
  231. protected int defineSizeColumnDefBlock() { return 25; }
  232. protected int defineSizeIndexEntryMask() { return 453; }
  233. protected int definePagesPerUsageMapPage() { return 4092 * 8; }
  234. protected Charset defineCharset() { return Charset.forName("UTF-16LE"); }
  235. }
  236. }