KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > h2 > store > FileStore


1 /*
2  * Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
3  * Initial Developer: H2 Group
4  */

5 package org.h2.store;
6
7 import java.io.File JavaDoc;
8 import java.io.IOException JavaDoc;
9 import java.io.RandomAccessFile JavaDoc;
10 import java.lang.ref.Reference JavaDoc;
11 import java.sql.SQLException JavaDoc;
12
13 import org.h2.engine.Constants;
14 import org.h2.message.Message;
15 import org.h2.security.SecureFileStore;
16 import org.h2.util.ByteUtils;
17 import org.h2.util.FileUtils;
18 import org.h2.util.TempFileDeleter;
19
20 public class FileStore {
21
22     public static final int HEADER_LENGTH = 3 * Constants.FILE_BLOCK_SIZE;
23
24     protected String JavaDoc name;
25     protected DataHandler handler;
26     private byte[] magic;
27
28     private RandomAccessFile JavaDoc file;
29     private long filePos;
30     private Reference JavaDoc autoDeleteReference;
31
32     public static FileStore open(DataHandler handler, String JavaDoc name, byte[] magic) throws SQLException JavaDoc {
33         return open(handler, name, magic, null, null, 0);
34     }
35
36     public static FileStore open(DataHandler handler, String JavaDoc name, byte[] magic, String JavaDoc cipher, byte[] key) throws SQLException JavaDoc {
37         return open(handler, name, magic, cipher, key, Constants.ENCRYPTION_KEY_HASH_ITERATIONS);
38     }
39     
40     public static FileStore open(DataHandler handler, String JavaDoc name, byte[] magic, String JavaDoc cipher, byte[] key, int keyIterations) throws SQLException JavaDoc {
41         FileStore store;
42         if(FileUtils.isInMemory(name)) {
43             store = new MemoryFileStore(handler, name, magic);
44         } else if(cipher == null) {
45             store = new FileStore(handler, name, magic);
46         } else {
47             store = new SecureFileStore(handler, name, magic, cipher, key, keyIterations);
48         }
49         return store;
50     }
51
52     protected FileStore(DataHandler handler, String JavaDoc name, byte[] magic) throws SQLException JavaDoc {
53         this.handler = handler;
54         this.name = name;
55         this.magic = magic;
56         try {
57             FileUtils.createDirs(name);
58             File JavaDoc f = new File JavaDoc(name);
59             if(f.exists() && !f.canWrite()) {
60                 file = FileUtils.openRandomAccessFile(name, "r");
61             } else {
62                 // file = new RandomAccessFile(name, "rws");
63
file = FileUtils.openRandomAccessFile(name, "rw");
64             }
65         } catch(IOException JavaDoc e) {
66             throw Message.convert(e);
67         }
68     }
69
70     protected FileStore(DataHandler handler, byte[] magic) {
71         this.handler = handler;
72         this.magic = magic;
73     }
74
75     protected byte[] generateSalt() {
76         return magic;
77     }
78
79     protected void initKey(byte[] salt) {
80         // do nothing
81
}
82
83     protected void checkWritingAllowed() throws SQLException JavaDoc {
84         if(handler != null) {
85             handler.checkWritingAllowed();
86         }
87     }
88
89     protected void checkPowerOff() throws SQLException JavaDoc {
90         if(handler != null) {
91             handler.checkPowerOff();
92         }
93     }
94
95     public void init() throws SQLException JavaDoc {
96         int len = Constants.FILE_BLOCK_SIZE;
97         byte[] salt;
98         if(length() < HEADER_LENGTH) {
99             // write unencrypted
100
writeDirect(magic, 0, len);
101             salt = generateSalt();
102             writeDirect(salt, 0, len);
103             initKey(salt);
104             // write (maybe) encrypted
105
write(magic, 0, len);
106         } else {
107             // write unencrypted
108
seek(0);
109             byte[] buff = new byte[len];
110             readFullyDirect(buff, 0, len);
111             if(ByteUtils.compareNotNull(buff, magic) != 0) {
112                 throw Message.getSQLException(Message.FILE_VERSION_ERROR_1, name);
113             }
114             salt = new byte[len];
115             readFullyDirect(salt, 0, len);
116             initKey(salt);
117             // read (maybe) encrypted
118
readFully(buff, 0, Constants.FILE_BLOCK_SIZE);
119             if(ByteUtils.compareNotNull(buff, magic) != 0) {
120                 throw Message.getSQLException(Message.FILE_ENCRYPTION_ERROR_1, name);
121             }
122         }
123     }
124
125     public void close() throws IOException JavaDoc {
126         if(file != null) {
127             try {
128                 file.close();
129             } finally {
130                 file = null;
131             }
132         }
133     }
134     
135     public void closeSilently() {
136         if(file != null) {
137             try {
138                 file.close();
139             } catch(IOException JavaDoc e) {
140                 file = null;
141             }
142         }
143     }
144
145     public void closeAndDeleteSilently() {
146         if(file != null) {
147             closeSilently();
148             TempFileDeleter.deleteFile(autoDeleteReference, name);
149             name = null;
150         }
151     }
152
153     protected void readFullyDirect(byte[] b, int off, int len) throws SQLException JavaDoc {
154         readFully(b, off, len);
155     }
156
157     public void readFully(byte[] b, int off, int len) throws SQLException JavaDoc {
158         if(Constants.CHECK && len < 0) {
159             throw Message.getInternalError("read len "+len);
160         }
161         if(Constants.CHECK && len % Constants.FILE_BLOCK_SIZE != 0) {
162             throw Message.getInternalError("unaligned read "+name+" len "+len);
163         }
164         checkPowerOff();
165         try {
166             file.readFully(b, off, len);
167         } catch (IOException JavaDoc e) {
168             throw Message.convert(e);
169         }
170         filePos += len;
171     }
172
173     public void seek(long pos) throws SQLException JavaDoc {
174         if(Constants.CHECK && pos % Constants.FILE_BLOCK_SIZE != 0) {
175             throw Message.getInternalError("unaligned seek "+name+" pos "+pos);
176         }
177         try {
178             if(pos != filePos) {
179                 file.seek(pos);
180                 filePos = pos;
181             }
182         } catch (IOException JavaDoc e) {
183             throw Message.convert(e);
184         }
185     }
186
187     protected void writeDirect(byte[] b, int off, int len) throws SQLException JavaDoc {
188         write(b, off, len);
189     }
190
191     public void write(byte[] b, int off, int len) throws SQLException JavaDoc {
192         if(Constants.CHECK && len < 0) {
193             throw Message.getInternalError("read len "+len);
194         }
195         if(Constants.CHECK && len % Constants.FILE_BLOCK_SIZE != 0) {
196             throw Message.getInternalError("unaligned write "+name+" len "+len);
197         }
198         checkWritingAllowed();
199         checkPowerOff();
200         try {
201             file.write(b, off, len);
202         } catch (IOException JavaDoc e) {
203             if(freeUpDiskSpace()) {
204                 try {
205                     file.write(b, off, len);
206                 } catch (IOException JavaDoc e2) {
207                     throw Message.convert(e2);
208                 }
209             } else {
210                 throw Message.convert(e);
211             }
212         }
213         filePos += len;
214     }
215
216     private boolean freeUpDiskSpace() throws SQLException JavaDoc {
217         if(handler == null) {
218             return false;
219         }
220         handler.freeUpDiskSpace();
221         return true;
222     }
223
224     public void setLength(long newLength) throws SQLException JavaDoc {
225         if(Constants.CHECK && newLength % Constants.FILE_BLOCK_SIZE != 0) {
226             throw Message.getInternalError("unaligned setLength "+name+" pos "+newLength);
227         }
228         checkPowerOff();
229         checkWritingAllowed();
230         try {
231             FileUtils.setLength(file, newLength);
232         } catch (IOException JavaDoc e) {
233             if(freeUpDiskSpace()) {
234                 try {
235                     FileUtils.setLength(file, newLength);
236                 } catch (IOException JavaDoc e2) {
237                     throw Message.convert(e2);
238                 }
239             } else {
240                 throw Message.convert(e);
241             }
242         }
243     }
244
245     public long length() throws SQLException JavaDoc {
246         try {
247             if(Constants.CHECK && file.length() % Constants.FILE_BLOCK_SIZE != 0) {
248                 long newLength = file.length() + Constants.FILE_BLOCK_SIZE - (file.length() % Constants.FILE_BLOCK_SIZE);
249                 FileUtils.setLength(file, newLength);
250                 throw Message.getInternalError("unaligned file length "+name+" len "+file.length());
251             }
252             return file.length();
253         } catch (IOException JavaDoc e) {
254             throw Message.convert(e);
255         }
256     }
257
258     public long getFilePointer() throws SQLException JavaDoc {
259         if(Constants.CHECK2) {
260             try {
261                 if(file.getFilePointer() != filePos) {
262                     throw Message.getInternalError();
263                 }
264             } catch (IOException JavaDoc e) {
265                 throw Message.convert(e);
266             }
267         }
268         return filePos;
269     }
270
271     public void sync() {
272         try {
273             file.getFD().sync();
274         } catch(IOException JavaDoc e) {
275             // TODO log exception
276
}
277     }
278
279     public void autoDelete() {
280         autoDeleteReference = TempFileDeleter.addFile(name, this);
281     }
282
283     public void stopAutoDelete() {
284         TempFileDeleter.stopAutoDelete(autoDeleteReference, name);
285         autoDeleteReference = null;
286     }
287
288 }
289
Popular Tags